tmap
tmap copied to clipboard
Multi-variable / multivariate specification functions
Example using the stars raster:
L7file = system.file("tif/L7_ETMs.tif", package = "stars")
L7 = read_stars(L7file)
### working but gives warning
tm_shape(L7) +
tm_raster(3, 2, 1)
# Warning message:
# In value[[3L]](cond) : could not rename the data.table
### not working gives error
tm_shape(L7) +
tm_rgb(3, 2, 1)
# Error: palette should be a character value
# In addition: Warning message:
# In value[[3L]](cond) : could not rename the data.table
Thx. It's already some time ago that I've worked on stars objects with bands and attributes. So I have to recall which function calls should be supported and that the 'correct' approach is.
At least, tmap4 does the 'multivariate' stuff via tm_mv
and tm_mv_dim
.
Since L7
is a stars object with a dimension called band
this is the correct (but tedious looking) code:
tm_shape(L7) +
tm_raster(col = tm_mv_dim("band", c(3, 2, 1)), col.scale = tm_scale_rgb())
Or, shorter:
tm_shape(L7) +
tm_rgb(tm_mv_dim("band", c(3, 2, 1)))
Have to make sure your code works as well (backwards compatibility) or at least throws some useful errors.
Do you know if this code worked in earlier tmap4 development versions?
FYI: This works as well
L7split = split(L7)
tm_shape(L7split) +
tm_rgb(tm_mv("X3", "X2", "X1"))
but tm_rgb()
does not because the default is tm_mv(3, 2, 1)
. So I need to make sure numbers are translated to attribute indices...
See the newly added examples of tm_rgb
. Now there are three functions to specify multivariate visual variables (such as rgb color channels:
-
tm_mv
that uses attribute/layer names -
tm_mv_shape_vars
that uses attribute/layer indices -
tm_mv_dim
that uses a (stars) dimension
Let me now how useful this is.
@mtennekes would it be possible to merge tm_mv
and tm_mv_shape_vars
into just one function that would react to either provided names or indices?
That's not so easy, because in general, the value specified for a visual variable (say col
) is either a data variable name (e.g. "life_exp"
) or a visual value (e.g. "#ABCDEF"
).
tm_mv
also follows this procedure, but for multivariate data. Therefore, tm_mv(1, 2, 3)
, could be processed as a multivariate visual value, so rgb(1,2,3, maxColorValue = 255)
. (Note: this does not work yet, because col
requires a color name/hex code; to make this work, I need to make use of the tm_scale_rgb in order to obtain maxColorValue).
For tm_raster
, I needed a default specification to show all attributes, for example for tm_shape(land) + tm_raster()
.
That lead to the function tm_shape_vars
. For tm_rgb
is was relatively easy to extend this function for multivariante data. Hence tm_mv_shape_vars
.
That is the history behind these functions and their names. Suggestion to make this more intuitive (while still possible to implement) are welcome.
@mtennekes, what do you think about updating the names:
-
tm_mv_dim
that uses a (stars) dimension -
tm_mv_lyr
that uses attribute/layer indices
?
I like those names @Nowosad before we need to make sure to cover all use cases. Not just raster objects, but also vector objects. For instance, the function tm_mv_shape_vars
also applies to polygons, so tm_mv_lyr
would be a less intuitive name here.
Currently this family of functions is:
1 tm_mv(...)
2 tm_mv_dim(x, values)
3 tm_shape_vars(ids, n)
4 tm_mv_shape_vars(ids, n)
Examples of vector shapes:
tm_shape(World) +
tm_polygons(tm_mv("HPI", "well_being"))
tm_shape(World) +
tm_polygons(tm_shape_vars(n = 3))
tm_shape(World) +
tm_polygons(tm_mv_shape_vars(ids = c(4, 9)))
So what would be the most intuitive names? We could also combine tm_mv
and tm_mv_shape_vars
and call it tm_mv_vars
. For the multiple-variables (but not multivariate) case, so fill = c("HPI", "well_being")
and fill = tm_shape_vars(n = 3)
, we could introduce tm_vars
. So then we have:
1 tm_vars(..., ids, n)
2 tm_mv_vars(..., ids, n)
3 tm_mv_dim(x, values)
Then, tm_mv_vars
is the same as your suggestion tm_mv_lyr
(variable = layer = attribute) => not sure which of these names is the most intuitive.
Ignore my previous post. I've managed to make it into one function: tm_vars
https://github.com/r-tmap/tmap/commit/4e7f35d084881497455e3e2dec7a24a93751fb45
@Nowosad @marine-ecologist Please check this script https://github.com/r-tmap/tmap/blob/master/sandbox/vv2.R, which we should convert to vignette(s).
tm_vars
will have the arguments:
-
x
which can be either a vector variable names (previously the...
), or variable indices (previouslyids
), or a single dimension name -
values
only used in casex
is a dimension -
n
the firstn
variables in casex
is not specified (and in casex
is a dimension andvalues
are not specified, the firstn
unique (sorted) values of this dimension. -
multivariate
. FALSE means multiple variables (facets), TRUE means multivariate (e.g. bivariate choropleth)
This has breaking changes w.r.t. the earlier v4 implementation of multivariate visual variables. E.g.
tm_shape(World) +
tm_polygons(tm_mv("HPI", "well_being"))
will become
tm_shape(World) +
tm_polygons(tm_vars(c("HPI", "well_being")))
Awesome! I think that this is much more intuitive.
I checked the script, and have a few comments (reprex attached below):
- The "complex stars" section returns a few identical outputs based on different tmap codes. I think this is not as expected (?).
- The terra section gives a warning.
- The glyphs section returns an error.
library(tmap)
file = system.file("tif/L7_ETMs.tif", package = "stars")
# 1 complex stars ???
# 2 -- spurious warning
L7_terra = terra::rast(file)
tm_shape(L7_terra) +
tm_rgb(tm_vars(dimvalues = 1:3, multivariate = TRUE))
#> Warning in apply_scale(s, l, crt, val, unm, nm__ord, "legnr", "crtnr", sortRev,
#> : Too many variables defined
# 3 error
library(tmap.glyphs)
tm_shape(NLD_prov) +
tm_polygons() +
tm_donuts(parts = tm_vars(c("origin_native", "origin_west", "origin_non_west"), multivariate = TRUE),
size = "population",
size.scale = tm_scale_continuous(values.scale = 1),
fill.scale = tm_scale_categorical(values = "brewer.dark2"))
#> Error in get(fun, mode = "function", envir = envir): object 'tmapScaleComposition' of mode 'function' was not found
Thx @Nowosad
- The "complex stars" section returns a few identical outputs based on different tmap codes. I think this is not as expected (?).
Actually, it is as expected, just to show the multiple ways to Rome. Maybe it would be better to ignore the output, and show multiple tmap code chunks that produce the same map.
- The terra section gives a warning.
Fixed. The problem was in the tmap code: terra doesn't use dimensions, so dimvalues are ignored. By default all (in this case 6) variables are shown. Perhaps the warning could be a little more helpful.
- The glyphs section returns an error.
Fixed! (please reinstall tmap.glyphs with the latest gh version)
Hi @mtennekes -- just to let you know, I am still getting warnings/errors after updating the packages from GitHub, see:
# remotes::install_github("r-tmap/tmap")
# remotes::install_github("r-tmap/tmap.glyphs")
library(tmap)
file = system.file("tif/L7_ETMs.tif", package = "stars")
# 1 -- spurious warning
L7_terra = terra::rast(file)
tm_shape(L7_terra) +
tm_rgb(tm_vars(dimvalues = 1:3, multivariate = TRUE))
#> Warning in apply_scale(s, l, crt, val, unm, nm__ord, "legnr", "crtnr", sortRev,
#> : Too many variables defined
# 2 -- glyphs
library(tmap.glyphs)
tm_shape(NLD_prov) +
tm_polygons() +
tm_donuts(parts = tm_vars(c("origin_native", "origin_west", "origin_non_west"), multivariate = TRUE),
size = "population",
size.scale = tm_scale_continuous(values.scale = 1),
fill.scale = tm_scale_categorical(values = "brewer.dark2"))
#> Error in get_scale_defaults(scale, o, aes, layer, cls, ct): could not find function "get_scale_defaults"