rggplot2scatterpie

labeller argument in geom_scatterpie_legend() doesn’t produce expected results


I am creating a world map with pie charts depicting sampling conducted.

I am having trouble getting the labeller option within geom_scatterpie_legend() - it appears to be producing non-sensical labels. The radius of my pies is set by Plot3.dat$lradius. Plot3.dat$lradius is equal to log(Plot3.dat$radius + 1). Despite my radius being on the log scale, I do not want the labels of my legend to be on the log scale, hence I am trying to use the labeller option to back-transform my legend labels. However, the back-transformation of the labels does not seem to produce results in line with the coded labeller function.

I have tried running this on a second machine and I get the same result.

ggplot() +
  geom_polygon(data = countries, 
               aes(x = long, y = lat, group = group), 
               colour = "black", fill = NA) +
  geom_scatterpie(data = Plot3.dat, 
                  aes(x = long, y = lat, r = lradius), 
                  sorted_by_radius = T, 
                  cols = c("Prop.carn", "Prop.herb", "Prop.om")) +
  geom_scatterpie_legend(c(log(2), log(31), log(151), log(751)), 
                         x = -150.54, y = -50, n = 4, 
                         labeller = function(x) round(exp(x) - 1, digits = 0))

The legend labels that should be produced for the four concentric circles are 1, 30, 150 and 750. As you can see the produced legend labels are 0, 6, 54 and 402.

This is the plot produced: plot produced.

This is my data:

Plot3.dat <- structure(list(Country = structure(1:28, levels = c("Australia", 
"Belgium", "Cambodia", "Canada", "Ecuador", "England", "Ethiopia", 
"France", "French Polynesia", "Germany", "India", "Indonesia", 
"Iran", "Israel", "Japan", "Malaysia", "Mexico", "Mongolia", 
"Morocco", "New Zealand", "Pakistan", "Philipines", "Spain", 
"Switzerland", "Thailand", "United Kingdom", "United States of America", 
"Wales"), class = "factor"), Carnivore = c(566L, 0L, 0L, 0L, 
2L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 147L, 
0L, 0L, 0L, 1L, 0L, 0L, 88L, 0L), Herbivore = c(242L, 0L, 0L, 
34L, 0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L, 0L, 3L, 0L, 0L, 0L, 0L, 
0L, 46L, 0L, 0L, 0L, 0L, 0L, 0L, 79L, 0L), Omnivore = c(130L, 
1L, 24L, 2L, 0L, 161L, 0L, 5L, 1L, 17L, 409L, 5L, 6L, 0L, 4L, 
11L, 4L, 2L, 1L, 728L, 278L, 4L, 6L, 0L, 27L, 10L, 282L, 1L), 
    lat = c(-25.2744, 50.5039, 12.5657, 56.1304, -1.8312, 52.3555, 
    9.145, 46.2276, -17.6797, 51.1657, 20.5937, -0.7893, 32.4279, 
    31.0461, 36.2048, 4.2105, 23.6345, 46.8625, 31.7917, -40.9006, 
    30.3753, 12.8797, 40.4637, 46.8182, 15.87, 55.3781, 37.0902, 
    52.1307), long = c(133.7751, 4.4699, 104.991, -106.3468, 
    -78.1834, -1.1743, 40.4897, 2.2137, -149.4068, 10.4515, 78.9629, 
    113.9213, 53.688, 34.8516, 138.2529, 101.9758, -102.5528, 
    103.8467, -7.0926, 174.886, 69.3451, 121.774, -3.7492, 8.2275, 
    100.9925, -3.436, -95.7129, -3.7837), Prop.carn = c(0.603411513859275, 
    0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.159609120521173, 
    0, 0, 0, 1, 0, 0, 0.195991091314031, 0), Prop.herb = c(0.257995735607676, 
    0, 0, 0.944444444444444, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 1, 
    0, 0, 0, 0, 0, 0.0499457111834962, 0, 0, 0, 0, 0, 0, 0.175946547884187, 
    0), Prop.om = c(0.138592750533049, 1, 1, 0.0555555555555556, 
    0, 1, 0, 0.5, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0.790445168295331, 
    1, 1, 1, 0, 1, 1, 0.628062360801782, 1), radius = c(938, 
    1, 24, 36, 2, 161, 3, 10, 1, 17, 409, 5, 6, 3, 4, 11, 4, 
    2, 1, 921, 278, 4, 6, 1, 27, 10, 449, 1), lradius = c(6.84481547920826, 
    0.693147180559945, 3.2188758248682, 3.61091791264422, 1.09861228866811, 
    5.08759633523238, 1.38629436111989, 2.39789527279837, 0.693147180559945, 
    2.89037175789616, 6.01615715969835, 1.79175946922805, 1.94591014905531, 
    1.38629436111989, 1.6094379124341, 2.484906649788, 1.6094379124341, 
    1.09861228866811, 0.693147180559945, 6.82654522355659, 5.63121178182137, 
    1.6094379124341, 1.94591014905531, 0.693147180559945, 3.3322045101752, 
    2.39789527279837, 6.10924758276437, 0.693147180559945)), row.names = c(NA, 
-28L), class = "data.frame")

Solution

  • IMHO you misunderstood the radius argument of geom_scatterpie_legend. It does not allow you to set your desired breaks but is simply used to provide the data range to be displayed in the legend. The breaks are computed under the hood using scales::breaks_extended.

    This can be seen from the following lines of code which first give the breaks chosen by geom_scatterpie_legend and the labels returned by your labeller function.

    radius <- c(log(2), log(31), log(151), log(751))
    labeller <- function(x) round(exp(x) - 1, digits = 0)
    
    breaks <- scales::breaks_extended(n = 4)(radius)
    
    breaks
    #> [1] 0 2 4 6
    
    labeller(breaks)
    #> [1]   0   6  54 402
    

    Unfortunately the computation of the breaks is "hard-coded" but you the function could be extended quite easily to allow to set custom breaks and to achieve your desired result. To this end I added a breaks argument to geom_scatterpie_legend.

    library(ggplot2)
    library(scatterpie)
    library(ggforce)
    
    countries <- map_data("world")
    
    # Copy and Paste from `scattterpie::geom_scatterpie_legend`
    
    geom_scatterpie_legend2 <- function (radius = NULL, breaks = NULL, x, y, n = 5, labeller) {
      if (n <= 1) {
        stop("The n argument requires larger than 1.")
      }
      if (is.null(breaks)) {
        radius <- (scales::breaks_extended(n = n))(radius)  
      } else {
        radius <- breaks
      }
      
      label <- FALSE
      if (!missing(labeller)) {
        if (!inherits(labeller, "function")) {
          stop("labeller should be a function for converting radius")
        }
        label <- TRUE
      }
      dd <- data.frame(r = radius, start = 0, end = 2 * pi, x = x, 
                       y = y + radius - max(radius), maxr = max(radius))
      if (label) {
        dd$label <- labeller(dd$r)
      }
      else {
        dd$label <- dd$r
      }
      list(geom_arc_bar(aes_(x0 = ~x, y0 = ~y, r0 = ~r, r = ~r, 
                             start = ~start, end = ~end), data = dd, inherit.aes = FALSE), 
           geom_segment(aes_(x = ~x, xend = ~x + maxr * 1.5, y = ~y + 
                               r, yend = ~y + r), data = dd, inherit.aes = FALSE), 
           geom_text(aes_(x = ~x + maxr * 1.6, y = ~y + r, label = ~label), 
                     data = dd, hjust = "left", inherit.aes = FALSE))
    }
    
    ggplot() +
      geom_polygon(
        data = countries,
        aes(x = long, y = lat, group = group),
        colour = "black", fill = NA
      ) +
      geom_scatterpie(
        data = Plot3.dat,
        aes(x = long, y = lat, r = lradius),
        sorted_by_radius = T,
        cols = c("Prop.carn", "Prop.herb", "Prop.om")
      ) +
      coord_quickmap() +
      geom_scatterpie_legend2(breaks = radius,
        x = -150.54, y = -50, n = 5,
        labeller = labeller
      )
    

    enter image description here