3

I am, in R and using ggplot2, plotting the development over time of several variables for several groups in my sample (days of the week, to be precise). An artificial sample (using long data suitable for plotting) is this:

library(tidyverse)

groups1 <- rep(1:2, each = 7 * 100)
groups2 <- rep(rep(1:7, times = 2), each = 100)
x <- rep(1:100, times = 14)
values <- c(rnorm(n = 700), rgamma(n = 700, shape = 2))

data <- tibble(x, groups1, groups2, values)

data %>% ggplot(mapping = aes(x = x, y = values)) + geom_line() + facet_grid(groups2 ~ groups1)

which gives

sample image

In this example, the first variable -- shown in the left column -- has unlimited range, while the second variable -- shown in the right column -- is weakly positive.

I would like to reflect this in my plot by allowing the Y axes to differ across the columns in this plot, i.e. set Y axis limits separately for the two variables plotted. However, in order to allow for easy visual comparison of the different groups for each of the two variables, I would also like to have the identical Y axes within each column.

I've looked at the scales option to facet_grid(), but it does not seem to be able to do what I want. Specifically,

  • passing scales = "free_x" allows the Y axes to vary across rows, while
  • passing scales = "free_y" allows the X axes to vary across columns, but
  • there is no option to allow the Y axes to vary across columns (nor, presumably, the X axes across rows).

As usual, my attempts to find a solution have yielded nothing. Thank you very much for your help!

BestGirl
  • 319
  • 1
  • 13
  • few comments: 1) always better to set a seed for better reproducibility, before "random" functions like `rnorm` 2) what do you mean with "unlimited range" ? I don't see a difference between the ranges between columns 1 and 2 – tjebo Jan 11 '23 at 13:54
  • 1
    In addition to @tjebo's recommendation to plot it twice and join with `patchwork`, this is similar to a [question I asked](https://stackoverflow.com/q/63550588/3358272) some time ago and got some (admittedly non-trivial) solutions that work; I stored it in a [gist](https://gist.github.com/r2evans/6057f7995c117bb787495dc14a228d5d), though I have not been able to keep up with questions about using/modifying it. – r2evans Jan 11 '23 at 14:06
  • 1
    @tjebo You're right about the seed, of course --- here the specific values are irrelevant, though, the only thing that matters is that the first variable (which is Gaussian here) can take any value, while the second (which is gamma here) can only take non-negative values. This is what I meant by "range", too. – BestGirl Jan 11 '23 at 15:44

1 Answers1

2

I think the easiest would to create a plot per facet column and bind them with something like {patchwork}. To get the facet look, you can still add a faceting layer.

library(tidyverse)
library(patchwork)

groups1 <- rep(1:2, each = 7 * 100)
groups2 <- rep(rep(1:7, times = 2), each = 100)
x <- rep(1:100, times = 14)
set.seed(42) ## always better to set a seed before using random functions
values <- c(rnorm(n = 700), rgamma(n = 700, shape = 2))

data <- tibble(x, groups1, groups2, values)
data %>%
  group_split(groups1) %>%
  map({
    ~ggplot(.x, aes(x = x, y = values)) +
  geom_line() + 
  facet_grid(groups2 ~ groups1)
  }) %>%
  wrap_plots()

Created on 2023-01-11 with reprex v2.0.2

tjebo
  • 21,977
  • 7
  • 58
  • 94