r-tmap / tmap

R package for thematic maps
https://r-tmap.github.io/tmap
GNU General Public License v3.0
868 stars 121 forks source link

xmod for tm_text #840

Open afolson-NOAA opened 8 months ago

afolson-NOAA commented 8 months ago

It looks like xmod and ymod are deprecated. Will there be an alternative method to offset tm_text so that it does not overlap tm_dots()?

mtennekes commented 8 months ago

Not deprecated, rather not implemented yet. What would be the best option from a user perspective (@afolson-NOAA @Nowosad ):

  1. Just a fixed x and y offset in terms of 'line heights'. As is done in tmap3
  2. Same, but in terms of coordinates
  3. As transformation variables, similar to size in tm_cartogram. Rather than distorting polygons, they offset the text position points.

The 3rd option is definitely the most elegant one I think, especially because we still need sophisticated to (re)implement automatic text labeling.

Say we would like to move the label "Paris" in the metro dataset. A work flow could be:

metro$offset_y = ifelse(metro$name == "Paris", 1, 0)

tm_shape(metro) +
   tm_dots(fill = "red") +
   tm_text("name", ymod = "offset_y")

Under the hood, the scaling function is tm_scale_asis, which takes the values and interprets them as line heights. I think line heights is still more intuitive than coordinates, but glad to hear your opinions. A minor issue is that the transformation takes place in step3 (step3_trans.R), so before knowing/using the plotting mode. That means that line height has to be estimated (e.g. coordinate y-diff / 20 * scale, assuming a standard map with scale =1 could contain about 20 lines of text).

The scaling function tm_scale_continuous could also be used. In that case, the values.range is by default defined as c(0, 1), meaning the highest data value ("offset_y") is mapped to 1. Not sure if it is useful though.

afolson-NOAA commented 8 months ago

Great to hear it is planned for inclusion in V4. I agree that coordinates are not very intuitive so Options 1 or 3 make sense to me. I'm a novice at tmap and spatial analysis in R, but have some older experience with regular GIS mapping software. I'm quite impressed with what can be done in R.

Nowosad commented 8 months ago

Hi all -- I also prefer solution 1 or 3. That being said -- I think it would be good to start by thinking about a larger picture. As @mtennekes mentioned, automatic text labeling is the long term goal, so it would make sense, in my opinion, to understand what is needed for that purpose.

mtennekes commented 8 months ago

Working:

## xymod
metro$initial = substr(metro$name,1,1)
metro$az = (match(metro$initial, LETTERS)-1) /25

tm_shape(metro) +
    tm_dots("red") +
    tm_text("initial", ymod = "az")

image

Just a toy example where the ymod is determined by the first letter of the city name.

First, I tried to implement a variable called xymod, because the automatic text labeling involves both x and y. However, that was too complex. Automatic text labeling can be done with via some additional arguments that can be passed on to tmapTransCentroid.

mtennekes commented 8 months ago

FYI, I added tm_labels, which does the automatic point labeling. Point labeling is based on car::pointLabel. Also added text rotation. See examples from tm_text.

For tm_labels we could add pointer lines. Will have to think about that. And tm_markers can be implemented.

mtennekes commented 8 months ago

Another thing: the layer options were contained in mapping.args and trans.args. However, I've migrated them back in to the layer function roots to make them better accessible. (Downside is the organisation of arguments).