tmap icon indicating copy to clipboard operation
tmap copied to clipboard

New feature: a multiple-column legend

Open taozhou2020 opened this issue 1 year ago • 4 comments

It appears that creating a legend with multiple columns has not yet been possible, but would be a nice-to-have feature. Will this be achieved in future versions?

taozhou2020 avatar Feb 07 '24 16:02 taozhou2020

It is definitely possible to implement, but it does take quite some time. I am currently focussed on getting v4 on CRAN, so this has lower priority for me.

To help you out, there is a manual workaround:

library(tmap)
tm_shape(World) + 
    tm_polygons("HPI")



pal = cols4all::c4a("hcl.blues3", n = 7)
palna = cols4all::c4a_na("hcl.blues3")

tm_shape(World) + 
    tm_polygons("HPI", fill.legend = tm_legend_hide()) +
    tm_add_legend(labels = c("10 to 15", "15 to 20", "20 to 25", "25 to 30"), fill = pal[1:4], type = "fill", title = "HPI") +
    tm_add_legend(labels = c("30 to 35", "35 to 40", "40 to 45", "Missing"), fill = c(pal[5:7], palna), type = "fill", title = " ", stack = "horizontal")

Created on 2024-02-15 with reprex v2.1.0

mtennekes avatar Feb 15 '24 16:02 mtennekes

Thanks very much @mtennekes . I've tried this workaround in v3.99.9000 which was installed by the following code: install.packages('tmap', repos = c('https://r-tmap.r-universe.dev', 'https://cloud.r-project.org'))

An issue still occurs when the colour palette is changed. The colour of the manually added legend is inconsistent with the colour in the map, whatever the palette changes. Examples are as follows (for simplicity, missing values are ignored).

e.g. 1:

pal = cols4all::c4a("hcl.green_orange", n = 7)

tm_shape(World) + 
  tm_polygons("HPI", fill.legend = tm_legend_hide()) +
  tm_add_legend(labels = c("10 to 15", "15 to 20", "20 to 25", "25 to 30"), fill = pal[1:4], type = "fill", title = "HPI", position = c("left", "bottom"), frame = FALSE) +
  tm_add_legend(labels = c("30 to 35", "35 to 40", "40 to 45"), fill =pal[5:7], type = "fill", title = " ", stack = "horizontal", position = c("left", "bottom"), frame = FALSE)
green_orange

e.g. 2:

pal = viridis::turbo(7)

tm_shape(World) + 
  tm_polygons("HPI", fill.legend = tm_legend_hide()) +
  tm_add_legend(labels = c("10 to 15", "15 to 20", "20 to 25", "25 to 30"), fill = pal[1:4], type = "fill", title = "HPI", position = c("left", "bottom"), frame = FALSE) +
  tm_add_legend(labels = c("30 to 35", "35 to 40", "40 to 45"), fill =pal[5:7], type = "fill", title = " ", stack = "horizontal", position = c("left", "bottom"), frame = FALSE)
turbo

I'd appreciate your suggestions.

taozhou2020 avatar Feb 17 '24 22:02 taozhou2020

@taozhou2020, you also need to update the palette of the main (not only the legend) -- I think that part should like something like:

  tm_polygons("HPI", fill.legend = tm_legend_hide(), fill.scale = tm_scale(values = pal)) +

Nowosad avatar Feb 18 '24 08:02 Nowosad

@Nowosad, Thanks for your help. It works now, and it also works perfectly with tm_dots:

pal = cols4all::c4a("-Spectral", n = 5)

tm_shape(Extreme_Rain_Days) + 
  tm_dots("Rain10mmDa", size = 0.5, fill.legend = tm_legend_hide(), fill.scale = tm_scale(values = pal)) +
  tm_add_legend(labels = c("0 to 20", "20 to 40"), fill = pal[1:2], type = "symbols", title = "Rain", position = c("left", "bottom"), frame = FALSE) +
  tm_add_legend(labels = c("40 to 60", "60 to 80"), fill = pal[3:4], type = "symbols", title = " ", stack = "horizontal", position = c("left", "bottom"), frame = FALSE) +
  tm_add_legend(labels = c("80 to 100"), fill = pal[5], type = "symbols", title = " ", stack = "horizontal", position = c("left", "bottom"), frame = FALSE) +
  tm_layout(frame = FALSE,
            inner.margins = c(0.1, 0.1, 0.1, 0.1),
            outer.margins = c(0.1, 0.1, 0.1, 0.1),
            asp = 0.61) +
  tm_title_in("Extreme Rain Days",tm_pos_in("center", "top"))
000076

taozhou2020 avatar Feb 18 '24 14:02 taozhou2020