11

Say I have the following data frame:

# Set seed for RNG
set.seed(33550336)

# Create toy data frame
loc_x <- c(a = 1, b = 2, c = 3)
loc_y <- c(a = 3, b = 2, c = 1)
scaling <- c(temp = 100, sal = 10, chl = 1) 

df <- expand.grid(loc_name = letters[1:3], 
                  variables = c("temp", "sal", "chl"), 
                  season = c("spring", "autumn")) %>% 
  mutate(loc_x = loc_x[loc_name],
         loc_y = loc_y[loc_name],
         value = runif(nrow(.)),
         value = value * scaling[variables])

which looks like,

# > head(df)
#   loc_name variables season loc_x loc_y     value
# 1        a      temp spring     1     3 86.364697
# 2        b      temp spring     2     2 35.222573
# 3        c      temp spring     3     1 52.574082
# 4        a       sal spring     1     3  0.667227
# 5        b       sal spring     2     2  3.751383
# 6        c       sal spring     3     1  9.197086

I want to plot these data in a facet grid using variables and season to define panels, like this:

g <- ggplot(df) + geom_point(aes(x = loc_name, y = value), size = 5)
g <- g + facet_grid(variables ~ season) 
g

enter image description here

As you can see, different variables have very different scales. So, I use scales = "free" to account for this.

g <- ggplot(df) + geom_point(aes(x = loc_name, y = value), size = 5)
g <- g + facet_grid(variables ~ season, scales = "free") 
g

enter image description here

Mucho convenient. Now, say I want to do this, but plot the points by loc_x and loc_y and have value represented by colour instead of y position:

g <- ggplot(df) + geom_point(aes(x = loc_x, y = loc_y, colour = value), 
                             size = 5)
g <- g + facet_grid(variables ~ season, scales = "free") 
g <- g + scale_colour_gradient2(low = "#3366CC", 
                                mid = "white", 
                                high = "#FF3300", 
                                midpoint = 50) 
g

enter image description here

Notice that the colour scales are not free and, like the first figure, values for sal and chl cannot be read easily.

My question: is it possible to do an equivalent of scales = "free" but for colour, so that each row (in this case) has a separate colour bar? Or, do I have to plot each variable (i.e., row in the figure) and patch them together using something like cowplot?

Dan
  • 11,370
  • 4
  • 43
  • 68
  • 2
    In short, no, there is no free scales option for any other scale than x and y. If you want separate color bars you'll indeed need to make separate plots. Or rescale your colors within each facet.. – Axeman Jan 02 '19 at 17:34
  • @Axeman Okay, good to know. Thanks for your reply. – Dan Jan 02 '19 at 17:41

1 Answers1

14

Using the development version of dplyr:

library(dplyr)
library(purrr)
library(ggplot2)
library(cowplot)

df %>% 
  group_split(variables, season) %>% 
  map(
    ~ggplot(., aes(loc_x, loc_y, color = value)) + 
      geom_point(size = 5) +
      scale_colour_gradient2(
        low = "#3366CC", 
        mid = "white", 
        high = "#FF3300", 
        midpoint = median(.$value)
      ) +
      facet_grid(~ variables + season, labeller = function(x) label_value(x, multi_line = FALSE))
  ) %>% 
  plot_grid(plotlist = ., align = 'hv', ncol = 2)

enter image description here

Axeman
  • 32,068
  • 8
  • 81
  • 94
  • That's a neat solution. Thanks! Is there a simple way of having each row on the same scale or would I have to have a different scale for each plot? By the way, I found that `ggarrange` from the `egg` package lines up plots better when the legend is of variable width due to labels of different lengths (e.g., cf `chl, spring` and `sal, spring`). – Dan Jan 02 '19 at 18:21
  • 1
    Oh right, I misread that you wanted it by row. Use `group_split(variables)` instead, and set `ncol` to 1 in `plot_grid`. You'll get three sets, with two facets each. Yes, there is different options for combining the plots! – Axeman Jan 02 '19 at 18:39