tmap icon indicating copy to clipboard operation
tmap copied to clipboard

continuous legend -> improve alignment

Open mtennekes opened this issue 10 months ago • 5 comments

UPDATE: (2025-03-05). The original issue was that the minimum and maximum value were not included in the gradient. This was solved by adding 'empty' ticks. However, those should not be printed for aesthetic reasons. That is also fixed. The remaining issue is that the legend needs a bit of alignment.

tm_shape(World) +
	tm_polygons("gender", fill.scale = tm_scale_continuous(values = "-brewer.blues"))

Image

Gradient starts at around 0.1, whereas:

min(World$gender, na.rm = T)
#> 0.009

mtennekes avatar Feb 12 '25 21:02 mtennekes

Fixed.

The problem was the following:

  • For each tick mark, a range is defined, e.g. in this example the '0.2' tick contains the gradient from 0.1 to 0.3, the '0.4' tick mark from 0.3 to 0.5, etc.
  • That means that all values from 0.1 to 0.9 can be covered by these ticks. However, in case there are data values in the range (0.0, 0.1] and [0.9, 1.0), these values were not contained in the legend. Note that when 0.0 and 1.0 are included, a new tick mark was created.

To solve this problem, I've added ticks to those cases:

Image

We can still decide to remove the 'empty' tick mark '- 0.0' for aesthetic reasons, but I do find it useful to read the scale.

mtennekes avatar Feb 13 '25 21:02 mtennekes

@mtennekes -- what should be the default in such cases? I (for aesthetic reasons mostly) prefer the first map. Also see the following examples (especially in the last two cases, the current default is not too pleasing, imo).

library(tmap)
library(spData)
library(dplyr)

us_states = left_join(us_states, us_states_df, by = c("NAME" = "state"))

tm_shape(us_states) +
  tm_polygons(fill = "median_income_15",
              fill.legend = tm_legend(title = "",
                                      position = c("left", "bottom"))) +
  tm_crs("auto") +
  tm_title("Median Income in 2015 (USD)")


# updating the color scale
med_inc15 = median(us_states$median_income_15, na.rm = TRUE)

tm_shape(us_states) +
  tm_polygons(fill = "median_income_15",
              fill.scale = tm_scale_continuous(midpoint = med_inc15),
              fill.legend = tm_legend(title = "",
                                      position = c("left", "bottom"))) +
  tm_crs("auto") +
  tm_title("Median Income in 2015 (USD)")


tm_shape(us_states) +
  tm_polygons(fill = "median_income_15",
              fill.scale = tm_scale_continuous(midpoint = med_inc15),
              fill.legend = tm_legend(title = "",
                                      orientation = "landscape",
                                      frame = FALSE,
                                      position = c("left", "bottom"))) +
  tm_crs("auto") +
  tm_title("Median Income in 2015 (USD)")


tm_shape(us_states) +
  tm_polygons(fill = "median_income_15",
              fill.scale = tm_scale_continuous(midpoint = med_inc15),
              fill.legend = tm_legend(title = "",
                                      orientation = "landscape",
                                      frame = FALSE,
                                      width = 60,
                                      position = tm_pos_out("center", "bottom", "center"))) +
  tm_crs("auto") +
  tm_title("Median Income in 2015 (USD)")
#> [plot mode] fit legend/component: Some legend items or map compoments do not
#> fit well, and are therefore rescaled.
#> ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

Nowosad avatar Feb 27 '25 10:02 Nowosad

Agree. Unfortunately it is not possible yet to move the whole legend a bit to the left after the '20.000' tick mark is removed. That is by design, because the legend uses a grid layout, in your example one column for each tick. Even though the first tick is removed, the column cannot be removed, because there are still colors to be plotted in that column.

This could be improved by changing the grid layout of the legend. (That will be finetuning).

mtennekes avatar Feb 28 '25 16:02 mtennekes

Image

mtennekes avatar Mar 05 '25 09:03 mtennekes

Fixed, but the legend position needs to be repositioned/re-aligned.

mtennekes avatar Mar 05 '25 10:03 mtennekes