One can not rasterize non-numeric attributes into an array
using NaturalEarth, Rasters, GeometryOps
countries = naturalearth("admin_0_countries", 110);
dx = Dim{:X}(-180:180)
dy = Dim{:Y}(-90:90)
# you can not rasterize non-numeric attributes into an array
ras = rasterize(first, countries; res=1.0, fill=:NAME, missingval="test", crs=EPSG(4326));
# but you can create raster of non-numerical values
ras = Raster(fill("test", (dx, dy)))
#but again you can not raterize on-numeric attributes, even if one initializes a non-numeric array
ras = rasterize!(first, ras, countries; fill=:NAME, missingval="test", crs=EPSG(4326));
ERROR: MethodError: no method matching zero(::Type{String})
The function `zero` exists, but no method is defined for this combination of argument types.
Closest candidates are:
zero(::Type{Union{}}, Any...)
@ Base number.jl:310
zero(::Type{Dates.DateTime})
@ Dates ~/.julia/juliaup/julia-1.11.0-rc1+0.aarch64.apple.darwin14/share/julia/stdlib/v1.11/Dates/src/types.jl:458
zero(::Type{Dates.Date})
@ Dates ~/.julia/juliaup/julia-1.11.0-rc1+0.aarch64.apple.darwin14/share/julia/stdlib/v1.11/Dates/src/types.jl:459
...
Stacktrace:
[1] _reduce_init(f::typeof(first), ::Type{String})
@ Rasters ~/Documents/GitHub/Rasters.jl/src/methods/rasterize.jl:15
[2] Rasters.Rasterizer(geom::Vector{…}, fill::Symbol, fillitr::Vector{…}; reducer::Function, op::Nothing, missingval::String, shape::Nothing, eltype::Nothing, init::Nothing, boundary::Symbol, filename::Nothing, verbose::Bool, progress::Bool, threaded::Bool, kw::@Kwargs{…})
@ Rasters ~/Documents/GitHub/Rasters.jl/src/methods/rasterize.jl:133
[3] Rasters.Rasterizer(data::GeoJSON.FeatureCollection{…}; fill::Symbol, geomcolumn::Nothing, kw::@Kwargs{…})
@ Rasters ~/Documents/GitHub/Rasters.jl/src/methods/rasterize.jl:168
[4] Rasterizer
@ ~/Documents/GitHub/Rasters.jl/src/methods/rasterize.jl:145 [inlined]
[5] rasterize(data::GeoJSON.FeatureCollection{…}; to::Nothing, fill::Symbol, threaded::Bool, kw::@Kwargs{…})
@ Rasters ~/Documents/GitHub/Rasters.jl/src/methods/rasterize.jl:419
[6] rasterize(reducer::Function, data::GeoJSON.FeatureCollection{…}; kw::@Kwargs{…})
@ Rasters ~/Documents/GitHub/Rasters.jl/src/methods/rasterize.jl:396
[7] top-level scope
@ ~/Documents/GitHub/ItsLivePlayground.jl/src/issue_with_cellarea.jl:1
Some type information was truncated. Use `show(err)` to see complete types.
Can you do that in other languages?
But I think there will be a way around it. I just assumed numbers.
I highly doubt this can be done in any other language... but it would certainly be a nice to have
I think you could hack around this using categorical arrays for now, you'd basically rasterize the category in as an integer, then rebuild the raster with rebuild(raster, data = CategoricalArray(parent(raster), data_lookup)). But it would be pretty annoying to write.
Actually it works if you define some methods. But there are quite a few method ambiguities. Maybe we should have a default fallback, just to make things work?
julia> Rasters._reduce_init(f::Function, ::Type{String}, missingval) = ""
julia> Rasters._reduce_init(f, ::Type{String}, missingval) = ""
julia> Rasters._reduce_init(f::Nothing, ::Type{String}, missingval) = ""
julia> ras = rasterize(first, countries; res=1.0, fill=:NAME, missingval="test", crs=EPSG(4326))
Burning each geometry to a BitArray slice... 100%|██████████████████████████████████████████████████| Time: 0:00:01
╭───────────────────────────────╮
│ 361×174 Raster{String,2} NAME │
├───────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── dims ┐
↓ X Projected{Float64} -180.0:1.0:180.0 ForwardOrdered Regular Intervals{Start},
→ Y Projected{Float64} -90.0:1.0:83.0 ForwardOrdered Regular Intervals{Start}
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── metadata ┤
Metadata of Dict{Any, Any}()
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── raster ┤
extent: Extent(X = (-180.0, 181.0), Y = (-90.0, 84.0))
missingval: "test"
crs: EPSG:4326
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
↓ → -90.0 -89.0 -88.0 -87.0 -86.0 -85.0 … 72.0 73.0 74.0 75.0 76.0 77.0 78.0 79.0 80.0 81.0 82.0 83.0
-180.0 "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
-179.0 "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
-178.0 "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
⋮ ⋮ ⋱ ⋮ ⋮
177.0 "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
178.0 "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
179.0 "Antarctica" "Antarctica" "Antarctica" "Antarctica" "Antarctica" "test" … "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
180.0 "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test" "test"
I would propose something on the lines of:
_reduce_init(f, x, missingval) = _placeholder_value(x)
_placeholder_value(x) = zero(x)
_placeholder_value(x::String) = ""
# ...
then users can define _placeholder_value and this just works.
If, without defining those methods, you define init in rasterize, it errors out in _get_eltype_missingval. So we could replace all references to zero with references to _placeholder_value.
Rasterizing the continent names 😂
Maybe we can call it _zeroval and allow it as a zeroval keyword later on.
But we'll have to remember what it's zeroness is actually used for to get the name right, I don't! Something somewhere in how the reductions work. But I also think in many cases it's not even used
I think this could just be the init value in most cases?
Yeah need to look at the alg some time. Sometimes there is a reason it's different and after three rewrites there isn't anymore but the code is still there
I am not sure what fixed this, but this is working now on the main of 0.14.7
Probably https://github.com/rafaqz/Rasters.jl/pull/1033 fixed it?
Oh wow I forgot I ran into this twice 🤣