I tried to create a plot with shared axis-labels. The problem was, that I wanted my legend under my plots, because my plots otherwise would be too compressed. I didn’t managed to creade a good plot with the eggpackage, because my x-axis labels was under my legend.
So I thought I might try a work around and also asked ChatGPT. The problem is, that the code belowe cuts off the last part of my x-axis lable. I’m new to R and don’t know if I made an obvious mistake. I don’t know if i did it right with the minimal, reproducible example.
Edit: I updatet my MRE, i can’t combine the 3 plots that it gives in one plot because this would include 12 lines with my original data.
set.seed(123)
spy <- data.frame(
UG_100 = runif(10, 0, 100),
UG_500 = runif(10, 0, 100),
UG_1000 = runif(10, 0, 100),
SK_0_disap = rbinom(10, 1, 0.5),
SK_Z_disap = rbinom(10, 1, 0.5),
SB_Z_disap = rbinom(10, 1, 0.5),
SB_0_disap = rbinom(10, 1, 0.5)
)
# packages
library(ggplot2)
library(viridis)
library(patchwork)
library(cowplot)
# Plots
combined_plot1 <- ggplot(spy, aes(x = UG_100)) +
geom_point(aes(y = SK_0_disap, color = "SK_0_disap")) +
geom_smooth(aes(y = SK_0_disap, color = "SK_0_disap", fill = "SK_0_disap"), method = "glm", se = TRUE, method.args = list(family = binomial), alpha = 0.2) +
theme_classic() +
labs(x = NULL, y = "Disappearance") +
scale_color_viridis_d(name = "Food Type", labels = c("sunflower seeds nwithout cinnamon")) +
scale_fill_viridis_d(name = "Food Type", labels = c("SK_0_disap"), guide = FALSE)
combined_plot_500_1 <- ggplot(spy, aes(x = UG_500)) +
geom_point(aes(y = SK_0_disap, color = "SK_0_disap")) +
geom_smooth(aes(y = SK_0_disap, color = "SK_0_disap", fill = "SK_0_disap"), method = "glm", se = TRUE, method.args = list(family = binomial), alpha = 0.2) +
theme_classic() +
labs(x = "Percentage of impervious surface cover", y = NULL) +
theme(axis.title.x = element_text(margin = margin(t = 20))) +
scale_color_viridis_d(name = "Food Type", labels = c("sunflower seeds nwithout cinnamon")) +
scale_fill_viridis_d(name = "Food Type", labels = c("SK_0_disap"), guide = FALSE)
combined_plot_1000 <- ggplot(spy, aes(x = UG_1000)) +
geom_point(aes(y = SK_0_disap, color = "SK_0_disap")) +
geom_smooth(aes(y = SK_0_disap, color = "SK_0_disap", fill = "SK_0_disap"), method = "glm", se = TRUE, method.args = list(family = binomial), alpha = 0.2) +
theme_classic() +
labs(x = NULL, y = NULL) +
scale_color_viridis_d(name = "Food Type", labels = c("sunflower seeds nwithout cinnamon")) +
scale_fill_viridis_d(name = "Food Type", labels = c("SK_0_disap"), guide = FALSE)
# Plot patchwork
combined_plot_all <- (combined_plot1 | combined_plot_500_1 | combined_plot_1000) +
plot_layout(guides = "collect") &
theme(legend.position = "bottom")
final_plot <- combined_plot_all +
plot_annotation(
tag_levels = 'a',
theme = theme(plot.tag = element_text(size = 14, face = "bold"))
) &
plot_annotation(
title = NULL,
subtitle = NULL,
caption = NULL,
tag_levels = c('a', 'b', 'c'),
theme = theme(plot.tag = element_text(size = 14, face = "bold"))
)
print(final_plot)
2
Here are two options to achieve your desired result. First, as I already mentioned in my comment you might consider using facetting which requires to reshape your data to long but allows to create one plot facetted by UG
.
library(tidyverse)
spy_long <- spy |>
tidyr::pivot_longer(starts_with("UG"), names_to = "ug", values_to = "value") |>
mutate(ug = factor(ug, paste0("UG_", c(100, 500, 1000))))
ggplot(spy_long, aes(x = value, y = SK_0_disap)) +
geom_point(aes(color = "SK_0_disap")) +
geom_smooth(
aes(color = "SK_0_disap", fill = "SK_0_disap"),
method = "glm", se = TRUE, method.args = list(family = binomial), alpha = 0.2
) +
scale_color_viridis_d(
name = "Food Type", labels = c("sunflower seeds nwithout cinnamon"),
aesthetics = c("color", "fill")
) +
facet_wrap(~ug) +
theme_classic() +
theme(legend.position = "bottom") +
labs(x = "Percentage of impervious surface cover", y = "Disappearance")
#> `geom_smooth()` using formula = 'y ~ x'
Second, if you want to stick with separate plots, e.g. because you want to have tags, then you can still get shared axes using axes="collect"
which works similar to guides="collect"
. But as with the latter, collecting will only work when the axes are identical, which means the should have the same name, labels, breaks and limits, i.e. you have to add the same axes titles to each of your plots and importantly make sure that all x axes share the same limits=
. Additionally, I avoid duplicating the code for each plot and instead specify most of the layers for the patch as a whole which requires to add layers using patchwork
‘s &
operator instead of ggplot2
‘s +
.
Note: In case you want only a shared x axis, it’s also possible to use axes="collect_x"
to collect only the x axes.
combined_plot_100 <- ggplot(spy, aes(x = UG_100, y = SK_0_disap))
combined_plot_500 <- ggplot(spy, aes(x = UG_500, y = SK_0_disap))
combined_plot_1000 <- ggplot(spy, aes(x = UG_1000, y = SK_0_disap))
library(patchwork)
(combined_plot_100 | combined_plot_500 | combined_plot_1000) +
plot_layout(guides = "collect", axes = "collect") +
plot_annotation(
tag_levels = "a",
theme = theme(plot.tag = element_text(size = 14, face = "bold"))
) &
geom_point(aes(color = "SK_0_disap")) &
geom_smooth(aes(color = "SK_0_disap", fill = "SK_0_disap"),
method = "glm", se = TRUE, method.args = list(family = binomial), alpha = 0.2
) &
scale_x_continuous(limits = c(0, 100)) &
scale_color_viridis_d(
name = "Food Type", labels = c("sunflower seeds nwithout cinnamon"),
aesthetics = c("color", "fill")
) &
theme_classic() &
theme(
axis.title.x = element_text(margin = margin(t = 20)),
legend.position = "bottom"
) &
labs(x = "Percentage of impervious surface cover", y = "Disappearance")
#> `geom_smooth()` using formula = 'y ~ x'
#> `geom_smooth()` using formula = 'y ~ x'
#> `geom_smooth()` using formula = 'y ~ x'
1