New feature: a multiple-column legend
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?
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
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)
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)
I'd appreciate your suggestions.
@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, 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"))