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.