5

My question is similar to this question but differs in an important aspect. I want to use different labelling functions created with the {scales} package for the tick mark labels (not the axis labels). Here's a reproducible example:

library(ggplot2)
library(scales)

mill <- number_format(scale = 1/1000000, suffix = " M")
thou <- number_format(scale = 1/1000, suffix = " k")

df <- data.frame(cond = rep(c("A", "B", "C"), each = 5),
           x_unit = rep(1:5, 3),
           y_unit = round(c(rnorm(5, 5e6, 10000),
                      rnorm(5, 5e6, 10000),
                      rnorm(5, 5000, 1000))))

ggplot(df, aes(x = x_unit, y = y_unit)) +
  geom_line() +
  scale_y_continuous(labels = mill) +
  facet_wrap(~ cond, scales = "free_y")

Example Output

You might already see where I'm going with this: For facet C, I want to use the labelling function thou and not mill. How would I do that? I'm pretty sure that the solution with the labeller argument in facet_wrap() from the question I linked above does not apply here, right?

swolf
  • 1,020
  • 7
  • 20

2 Answers2

5

You might be interested in ggh4x::scale_y_facet(). You give it a way to find the appropriate panel cond == "C" and give it a different label function than the default scale. It only works with facets where scales are free. Disclaimer: I'm the author of ggh4x.

library(ggplot2)
library(scales)

mill <- number_format(scale = 1/1000000, suffix = " M")
thou <- number_format(scale = 1/1000, suffix = " k")

df <- data.frame(cond = rep(c("A", "B", "C"), each = 5),
                 x_unit = rep(1:5, 3),
                 y_unit = round(c(rnorm(5, 5e6, 10000),
                                  rnorm(5, 5e6, 10000),
                                  rnorm(5, 5000, 1000))))

ggplot(df, aes(x = x_unit, y = y_unit)) +
  geom_line() +
  scale_y_continuous(labels = mill) +
  facet_wrap(~ cond, scales = "free_y") +
  ggh4x::scale_y_facet(cond == "C", labels = thou)

Created on 2022-11-24 by the reprex package (v2.0.1)

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • 1
    That is so great and it works, thanks for your answer and especially for your work on the package! – swolf Nov 24 '22 at 13:11
1

If you're happy with the suffixes being selected automatically, you can use the cut_long_scale() helper function available alongside the scale_cut option. The advantage over the manually defined scales is that you do not have to know in advance what magnitude the different number ranges will be.

library(ggplot2)
library(scales)

df <- data.frame(cond = rep(c("A", "B", "C"), each = 5),
                 x_unit = rep(1:5, 3),
                 y_unit = round(c(rnorm(5, 5e6, 10000),
                                  rnorm(5, 5e6, 10000),
                                  rnorm(5, 5000, 1000))))

ggplot(df, aes(x = x_unit, y = y_unit)) +
  geom_line() +
  scale_y_continuous(labels = number_format(scale_cut = cut_long_scale())) +
  facet_wrap(~ cond, scales = "free_y")

Created on 2022-11-27 by the reprex package (v2.0.1)

Robert Lew
  • 51
  • 3