Search code examples
rggplot2facetaxis-labels

How do I modify labels produced by scales package?


graphs

So I'm making pyramid visualizations. I'm using scale_y_continuous(labels = scales::label_number_si(accuracy = 0.1)) to produce the labels. However, I want to get rid of the negative sign on the female section of the graph.

I think the best way to keep the SI suffixes, but remove the negative sign is to modify the labels output by label_number_si, but labels = abs(label_number_si()) gives the following error: Error in abs: non-numeric argument to mathematical function

Any insight is appreciated.

EDIT: Use demo_continuous(c(-1e10,1e10), label = label_number_si()) labels should look as they do below EXCEPT that negative numbers should not have a "-" in front

enter image description here


Solution

  • I bet there's a simpler way to do this but I haven't figured it out yet.

    Here's an example that replicates your question's result using the normal scales::label_number_si:

    ggplot(data = data.frame(x = 1000*c(-5:-1, 1:5),
                             type = rep(1:2, each = 5))) +
      geom_col(aes(x,abs(x),fill = type), orientation = "y") +
      scale_x_continuous(labels = scales::label_number_si()) +
      facet_wrap(~type, scales = "free_x")
    

    enter image description here

    We could make a custom version of scales::label_number_si which makes them absolute values in the last step. To make this, I used command-click (Mac OS X) on the function name to see the underlying function's code, and then just pasted that into a new function definition with minor modifications.

    label_number_si_abs <- function (accuracy = 1, unit = NULL, sep = NULL, ...) 
    {
      sep <- if (is.null(unit)) 
        ""
      else " "
      function(x) {
        breaks <- c(0, 10^c(K = 3, M = 6, B = 9, T = 12))
        n_suffix <- cut(abs(x), breaks = c(unname(breaks), Inf), 
                        labels = c(names(breaks)), right = FALSE)
        n_suffix[is.na(n_suffix)] <- ""
        suffix <- paste0(sep, n_suffix, unit)
        scale <- 1/breaks[n_suffix]
        scale[which(scale %in% c(Inf, NA))] <- 1
        scales::number(abs(x), accuracy = accuracy, scale = unname(scale), 
               suffix = suffix, ...)
      }
    }
    

    We could replace with the custom function to get abs value labels:

    ggplot(data = data.frame(x = 1000*c(-5:-1, 1:5),
                             type = rep(1:2, each = 5))) +
      geom_col(aes(x,abs(x),fill = type), orientation = "y") +
      scale_x_continuous(labels = label_number_si_abs()) +
      facet_wrap(~type, scales = "free_x")
    

    enter image description here