简体   繁体   中英

Manual breaks of facet_wrap() in ggplot2

Problem

I am trying to understand how to provide y-axis breaks manually to facets, generated by the facet_wrap() function in ggplot2 in R .

Minimal reproducible example

Disclaimer: I have borrowed the following example from the R studio community

With the following code, you can specify the y-axis breaks based on the y-axis values in de dataset.

library(ggplot2)
diamonds2 <- subset(diamonds, !(cut == "Fair" & price > 5000))

my_breaks <- function(x) { if (max(x) < 6000) seq(0, 5000, 1000) else seq(0, 15000, 5000) }

ggplot(data = diamonds2, aes(x = carat, y = price)) +
  facet_wrap(~ cut, scales = "free_y") +
  geom_point() +
  scale_y_continuous(breaks = my_breaks)

在此处输入图片说明

Question

I would like to be able to specify the breaks manually, based on the facet (in this case: based on the 'cut' of the diamonds). For example, I would like to set the breaks for the 'Fair' cut to seq(1000, 2500, 5000) , the breaks for the 'Good' cut to seq(1500, 3000, 4500, 6000, ..., 15000) and the rest to seq(0,15000, 5000) .

Attempt

I thought that adapting the my_breaks function with an if-else-ladder, specifying the 'cut' would solve the problem, however, it doesn't:

my_breaks <- function(x) { 
  if (cut == "Fair") {seq(0, 5000, 1000) }
  else if (cut == "Good") {seq(1500,15000, 1500)}
  else { seq(0, 15000, 5000) }
}

It provides the error:

Error in cut == "Fair" : comparison (1) is possible only for atomic and list types

Is there another approach to manually provide the breaks to different facets?

Try defining each facet manually by filtering the data and then "patch" the plot up using patchwork package

library(ggplot2)
library(patchwork)

my_plot <- function(df, var, sc) {
  ggplot(data = df, aes(x = carat, y = price)) +
  facet_grid(~ {{var}}) +
  geom_point() +
  coord_cartesian(ylim = {{sc}})
}

diamonds2 <- subset(diamonds, !(cut == "Fair" & price > 5000))

p1 <- diamonds2 %>% filter(cut == "Fair") %>% my_plot(var = "Fair",  sc = c(0, 5000))
p2 <- diamonds2 %>% filter(cut == "Good") %>% my_plot(var = "Good",  sc = c(0, 15000))
p3 <- diamonds2 %>% filter(cut == "Very Good") %>% my_plot(var = "Very Good",  sc = c(0, 1000))
p4 <- diamonds2 %>% filter(cut == "Premium") %>% my_plot(var = "Premium",  sc = c(0, 500))
p5 <- diamonds2 %>% filter(cut == "Ideal") %>% my_plot(var = "Ideal",  sc = c(0, 20000))

p1+p2+p3+p3+p4+plot_layout(ncol = 3)

在此处输入图片说明

edit: I realized it was the y-axis breaks to be set pr. facet. In that case

my_plot <- function(df, var, my_breaks) {
  ggplot(data = df, aes(x = carat, y = price)) +
  facet_grid(~ {{var}}) +
  geom_point() +
  scale_y_continuous(breaks = {{my_breaks}})
}

library(ggplot2)
diamonds2 <- subset(diamonds, !(cut == "Fair" & price > 5000))

p1 <- diamonds2 %>% filter(cut == "Fair") %>% my_plot(var = "Fair",  my_breaks = seq(0, 5000, 1000))
p2 <- diamonds2 %>% filter(cut == "Good") %>% my_plot(var = "Good",  my_breaks = seq(1500,15000, 1500))
p3 <- diamonds2 %>% filter(cut == "Very Good") %>% my_plot(var = "Very Good",  my_breaks =seq(1500,15000, 5000))
p4 <- diamonds2 %>% filter(cut == "Premium") %>% my_plot(var = "Premium",  my_breaks = seq(1500,15000, 5000))
p5 <- diamonds2 %>% filter(cut == "Ideal") %>% my_plot(var = "Ideal",  my_breaks = seq(1500,15000, 5000))

p1+p2+p3+p3+p4+plot_layout(ncol = 3)

在此处输入图片说明

Edit2: A leaner way to do this using purrr

library(ggplot2)
library(patchwork)
library(purrr)
facets = diamonds2 %>% distinct(cut) %>% pull()
my_breaks = list(seq(0, 5000, 1000), seq(1500,15000, 1500), seq(1500,15000, 5000),
                 seq(1500,15000, 5000), seq(1500,15000, 5000))

plt_list <- purrr::map2(facets, my_breaks, ~my_plot(diamonds2, .x, .y))

Reduce('+', plt_list) + plot_layout(ncol = 3)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM