rggplot2number-formatting

ggplot2 and scales package: the parameter negative_parens = TRUE does not work


I was trying to use the scales package to produce formatting for a complex table. The following helper applies the label_percent and label_number_si functions from the scales package.

For some reason, the negative_parens = TRUE is not producing the correct output:

prettify_numbers_as_percent <- function(x){   
lapply(as.list(as.numeric(x)),label_percent(accuracy = 1,  suffix = "%", negative_parens = TRUE, sep = " ")) %>%

    unlist() %>%
    return() }



prettify_numbers_as_si <- function(x){
  lapply(as.list(as.numeric(x)), label_number_si(accuracy = 1,  negative_parens = TRUE, sep = " ")) %>%
    unlist() %>%
    return()
}

When I run

prettify_numbers_as_si(50000) 
prettify_numbers_as_percent(0.05)

I get the expected output:

"50K"
"5%"

When I run

prettify_numbers_as_si(-50000) 
prettify_numbers_as_percent(-0.05)

I get the incorrect output, despite the fact that negative_parens = TRUE is set:

"-50K"
"-5%"

Does anyone know why parameter setting is failing?


Solution

  • The issue is that while other functions in the scales package have negative_parens= as arguments, label_percent and label_number_si do not. Consequently, you have to write in that logic to your functions:

    new_percent <- function(x){
      perc <- lapply(
        as.list(as.numeric(x)),
        label_percent(
          accuracy=1, suffix = '%', sep=' '
        )
      ) %>%
      unlist()
    
      for(i in 1:length(perc)){
        if(substring(perc[i],1,1)=='-'){
          perc[i] <- paste0('(',substring(perc[i],2),')')
        }
      }
      return(perc)
    }
    
    new_numbers <- function(x){
      nums <- lapply(
        as.list(as.numeric(x)),
        label_number_si(
          accuracy = 1,  sep = " "
        )
      ) %>%
      unlist()
      for(i in 1:length(nums)){
        if (substring(nums[i],1,1)=='-'){
          nums[i] <- paste0('(',substring(nums[i],2),')')
        }
      }
      return(nums)
    }
    

    Since you know each value in your return that needs to be in parentheses will start with a "-", I'm using a for loop and substring() to iterate through each item and convert those that start with "-" to start and end with parentheses. Works pretty well:

    test_perc <- c(-0.5, -0.05, 1.2, .23, -0.13)
    test_nums <- c(6000,-60000, 74000, -56000000)
    
    > new_percent(test_perc)
    [1] "(50%)" "(5%)"  "120%"  "23%"   "(13%)"
    > new_numbers(test_nums)
    [1] "6K"    "(60K)" "74K"   "(56M)"