Search code examples
rr-leaflettmap

Is there a function to set a minimum size for symbols in tmap?


when tm_bubbles or tm_symbols is used to create bubbles or dots representing my data, categorized using size="data column of my choice", I am encountering a problem, where very small numbers in my dataset (let's say n=2 and my range is 10,2000), my bubble that represents x1=2000 is very visible on the screen, but x2=10 is so small that I can hardly see it on the screen. what I need is a function that sets a size.minimum for the bubbles. has anyone found a workaround for this problem? or can we create something like a size.minimum function for symbols?


Solution

  • That's how it currently looks like:

    library(tidyverse)
    library(tmap)
    library(sf)
    data("World")
    
    df_dummy <- tibble(size = c(10, 200, 2000), 
                       points = c(st_sfc(st_point(c(-30,20))), 
                                  st_sfc(st_point(c(7,52))),
                                  st_sfc(st_point(c(30,5))))) %>% 
      st_as_sf()
    
    tm_shape(World) +
      tm_fill(col = "gray") +
    tm_shape(df_dummy) +
      tm_bubbles(col = "red",
                 size = "size")
    

    enter image description here

    Option 1

    If you now add a df_dummy`<- df_dummy %>% mutate(size = log10(size)) your data is scaled differenty since we use the log10 function. Of course you loose the information about the "original" values in the legend but all symbols are visible:

    enter image description here

    Option 2

    Alternatively, you could simply generate a new column in which all values below a defined limit receive a specific size value (e.g. all values below 100 receive a size of 100). By this all values below this limit would be clipped to a single one which then can be used as your size parameter. In the following example the points with original sizes of 10, 50 and 80 are uniformly plotted with a clip size of 100. In the custom legend they are covered by the label <= 100.

    df_dummy <- tibble(size = c(10, 50, 80, 500, 2000), 
                       points = c(st_sfc(st_point(c(-30,20))), 
                                  st_sfc(st_point(c(7,52))),
                                  st_sfc(st_point(c(10,45))),
                                  st_sfc(st_point(c(15,35))),
                                  st_sfc(st_point(c(30,5))))) %>% 
      mutate(size = ifelse(size <= 100, 100, size)) %>% 
      st_as_sf()
    
    # see the tm_bubbles docs regarding the applied scaling
    bubble_sizes <- ((c(100, 500, 1000, 1500, 2000)) / 2000) ^ 0.5 * 2 
    
    tm_shape(World) +
      tm_fill(col = "gray") +
    tm_shape(df_dummy) +
      tm_bubbles(col = "red",
                 size = "size",
                 scale = 2,
                 border.col = "black",
                 legend.size.show = F,  
                     legend.col.show = F) +
      tm_add_legend("symbol",
                    size = bubble_sizes,
                    col = "red",
                    labels = c("<= 100","500","1000","1500", "2000"),
                    title = "custom legend")
    
    

    enter image description here