I want to create a flipped violin plot (with extra points for group means in geom_point() and lines from min to max values in geom_segment() ). I integrated the groups as facets with facet_grid(). The only thing I can not edit is the width of the violin plots of each facet. All groups have the same number of values and should be represented in the violin plots with the same area of the violin plots. When not using facets I have troubles with plotting the points and segments. Do you have any idea how to achieve that?
Input data:
dat1 <- data.frame(subgroup = c(rep(("mountain"), 150), rep(("upland"), 150), rep(("riparian"), 150)),
group = rep(c("birds"), 450),
value = sample(c(1:100), 450, replace = TRUE))
dat2 <- data.frame(subgroup = c(rep(("mountain"), 150), rep(("upland"), 150), rep(("riparian"), 150)),
group = rep(c("beetles"), 450),
value = sample(c(1:50), 450, replace = TRUE))
plot_data <- rbind(dat1, dat2)
plot_data$subgroup <- factor(plot_data$subgroup, levels = c("mountain", "upland","riparian") )
My plot code so far:
library(ggplot2)
library(dplyr)
plot_data %>%
ggplot( aes(x = interaction(group, subgroup), y = value, fill = subgroup, label = group)) +
geom_violin(width = 1, alpha = 0.5, scale = "area")+
geom_segment(data = plot_data %>%
dplyr::group_by(group, subgroup) %>%
dplyr::summarise(lower = min(value, na.rm =T),
upper = max(value, na.rm = T)),
aes(x = interaction(group, subgroup) , xend = interaction(group, subgroup),
y = lower, yend = upper), linewidth = 1, col = "grey10", alpha = 0.8)+
geom_point(data = plot_data %>%
dplyr::group_by(group, subgroup) %>%
dplyr::summarise(mean = mean(value, na.rm = T)),
aes(x= interaction(group, subgroup), y = mean), shape = 21, size = 4, col = "black")+
coord_flip()+
labs(y= "Model values", x="")+
facet_grid(group ~ ., scales = "free_y")+
theme_minimal()+
scale_x_discrete(labels= rev(c("riparian", "upland", "mountain")))+
theme(
axis.text.y = element_text(size = 12),
axis.text.x = element_text(size = 10),
axis.title.y = element_text(size = 20),
axis.title.x = element_text(size = 12),
strip.text.y = element_text(size = 14), # Customize facet labels
legend.position = "none")
the main issue I have is the violin width, here displayed correctly:
plot_data %>%
ggplot(aes(y = group, x = value, fill = subgroup)) +
geom_violin(width = 1, alpha = 0.5, scale = "area")
But here i struggle adding the points, lines and extra labels for the subgroups instead of a legend (like above)
You have incorrect width because you use facets with free scale.
To reorder your data, you can change the order of variable in the interaction
. Then you don't need to use facets. You can add group labels as the text annotations:
library(ggplot2)
library(ggtext)
plot_data %>%
ggplot( aes(y = interaction(subgroup, group), x = value, fill = subgroup, label = group)) +
geom_violin(width = 1, alpha = 0.5, scale = "area", orientation = "y") +
geom_segment(data = plot_data %>%
dplyr::group_by(group, subgroup) %>%
dplyr::summarise(lower = min(value, na.rm =T),
upper = max(value, na.rm = T)),
aes(y = interaction(subgroup, group) , yend = interaction(subgroup, group),
x = lower, xend = upper), linewidth = 1, col = "grey10", alpha = 0.8) +
geom_point(data = plot_data %>%
dplyr::group_by(subgroup, group) %>%
dplyr::summarise(mean = mean(value, na.rm = T)),
aes(y = interaction(subgroup, group), x = mean), shape = 21, size = 4, col = "black") +
labs(x = "Model values", y = "") +
annotate(geom = "richtext", label = "birds", x = 100, y = 5, angle = -90, vjust = -0.2, size = 5, fill = "white", label.color = NA) +
annotate(geom = "richtext", label = "beetles", x = 100, y = 2, angle = -90, vjust = -0.2, size = 5, fill = "white", label.color = NA) +
theme_minimal()+
scale_y_discrete(labels= rev(rep(c("riparian", "upland", "mountain"), 2)))+
theme(
axis.text.y = element_text(size = 12),
axis.text.x = element_text(size = 10),
axis.title.y = element_text(size = 20),
axis.title.x = element_text(size = 12),
legend.position = "none")