Search code examples
rggplot2facet-wrap

Add dollar formatting to one plot in a facet wrap plot in ggplot


I am trying to add dollar formatting using the scales package scales::dollar_format() to a single plot (Sales) of a facet wrap plot

z <- data.frame(months = month.name, sales = runif(12, min = 3000000, max = 60000000), cases = round(runif(12, min = 100, max = 1000),0)) %>% pivot_longer(!months, names_to = "variable", values_to = "metric")

ggplot(data = z,
       aes(x = months, y = metric)) +
  geom_bar(stat = 'identity') +
  facet_wrap(~ variable, ncol = 1, scales = "free_y")

I've tried using scale_y_continuous(labels = scales::dollar_format()) but it obviously adds it to both.

How can I add this to only the Sales plot and not the Cases plot?


Solution

  • There is no elegant way to do this in vanilla ggplot2. In you particular case, because your two scales have very different ranges, you can hack a solution together by giving a function that conditionally formats the labels.

    library(ggplot2)
    library(tidyr)
    
    z <- data.frame(months = month.name, sales = runif(12, min = 3000000, max = 60000000), cases = round(runif(12, min = 100, max = 1000),0)) %>%
      pivot_longer(!months, names_to = "variable", values_to = "metric")
    
    p <- ggplot(data = z,
           aes(x = months, y = metric)) +
      geom_bar(stat = 'identity') +
      facet_wrap(~ variable, ncol = 1, scales = "free_y")
    
    p + scale_y_continuous(
      labels = ~ if (any(.x > 1e3)) scales::dollar(.x) else .x
    )
    

    If your case gets more complicated however, you could use ggh4x::facetted_pos_scales() to give a particular scale to a particular panel. (Disclaimer: I'm the author of ggh4x)

    p + ggh4x::facetted_pos_scales(y = list(
      variable == "sales" ~ scale_y_continuous(labels = scales::dollar_format())
    ))
    

    Created on 2022-03-09 by the reprex package (v2.0.1)