Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to harmonize axes within facet_wrap and scale="free_y"?

Tags:

r

ggplot2

I would like to draw boxplots of relationship between a continuous and a categorical variables (geom_boxplot with ggplot2), this for several situations (facet_wrap). Quite easy:

data("CO2")
ggplot(CO2, aes(Treatment, uptake) ) + 
  geom_boxplot(aes(Treatment, uptake), 
               col="black", fill="white", alpha=0, width=.5) + 
  geom_point(col="black", size=1.2) + 
  facet_wrap(~Type, ncol=3, nrow=6, scales= "free_y") + 
  theme_bw() + 
  ylab("Uptake")

The result: enter image description here

This is quite nice with this toy dataset, but applied to my own data (where facet_wrap enables me to plot 18 different graphs) the y-axes are hardly readable, with varying number of y-ticks and varying spacing between them:

enter image description here

What could be a nice way to harmonize the y-axes? (i.e., getting equal spacing between y-axes ticks, no matter what breaks are -these will necessarily change from a graph to another because the variation range of my continuous variable changes a lot)

Thank you very much for any help :)

like image 782
Chrys Avatar asked Aug 30 '18 16:08

Chrys


1 Answers

You can turn force each facet's limits to something relatively nice looking, by manually expanding each facet's values through the application of pretty() on the y-axis values & taking the first / last values.

The following is an example using the diamonds dataset:

# normal facet_wrap plot with many different y-axis scales across facets
p <- ggplot(diamonds %>% filter(cut %in% c("Fair", "Ideal")), 
       aes(x = cut, y = carat) ) + 
  geom_boxplot(col="black", fill="white", alpha=0, width=.5) + 
  geom_point(col="black", size=1.2) + 
  facet_wrap(~clarity, scales= "free_y", nrow = 2) + 
  theme_bw() + 
  ylab("Uptake")

p

plot

# modified plot with consistent label placements
p + 
  # Manually create values to expand the scale, by finding "pretty" 
  # values that are slightly larger than the range of y-axis values 
  # within each facet; set alpha = 0 since they aren't meant to be seen
  geom_point(data = . %>% 
               group_by(clarity) %>% #group by facet variable
               summarise(y.min = pretty(carat)[1],
                         y.max = pretty(carat)[length(pretty(carat))]) %>%
               tidyr::gather(key, value, -clarity), 
             aes(x = 1, y = value),
             inherit.aes = FALSE, alpha = 0) +

  # Turn off automatical scale expansion, & manually set scale breaks
  # as an evenly spaced sequence (with the "pretty" values created above
  # providing the limits for each facet). If there are many facets to
  # show, I recommend no more than 3 labels in each facet, to keep things
  # simple.
  scale_y_continuous(breaks = function(x) seq(from = x[1], 
                                              to = x[2], 
                                              length.out = 3), 
                     expand = c(0, 0))

plot2

like image 198
Z.Lin Avatar answered Oct 16 '22 16:10

Z.Lin