admin管理员组文章数量:1122832
I have tried using various different methods to be able to create one combined legend for my 4 ggplots, however, either it causes one of the graphs to be squished as compared to the other because the legend is within that plot area or it errors.
Here is a reproducible data set to work with and code for my graphs:
var=c("White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian")
gender=c("Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women")
p=c(25, 35, 45, 26, 57, 43,35, 45, 43, 36, 27, 53,23, 55, 25, 25, 37, 23)
n=c(50, 100, 96, 57, 56, 54,50, 90, 96, 57, 56, 54,60, 110, 66, 37, 56, 54)
year=c(2019,2019,2019,2019,2019,2019, 2020,2020,2020,2020,2020,2020,2021,2021,2021,2021,2021,2021)
df=data.frame(year,var,gender,n,p)
df$var=factor(df$var, levels=c("Black","Asian","White"))
df$year=factor(df$year, levels=c(2019, 2020, 2021))
# Create graphs for men
men1=ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 150)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Number diagnosed")
men2=ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 100)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed")
# Combine graphs
men_combined=ggarrange(men1, men2,
nrow=1, ncol=2
)
# Add title to figure
men_combined=annotate_figure(men_combined,
top = text_grob("\nMen",
color = "black", face = "bold", size = 25))
# Create graphs for women
women1=ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 150)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Number diagnosed")
women2=ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 100)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed")
# Combine graphs
women_combined=ggarrange(women1, women2,
nrow=1, ncol=2
)
# Add title to figure
women_combined=annotate_figure(women_combined,
top = text_grob("\nWomen",
color = "black", face = "bold", size = 25))
# Combine all together
all_plots=ggarrange(men_combined, women_combined,
nrow=2, ncol=1)`
I have tried using the following to help and I was able to get a common legend but it then did not work when I tried using annotate_figure as I need to have a title above each to show the gender. Add a common Legend for combined ggplots
This is code I used which then did not work when I added the 'Men' and 'Women' titles:
grid_arrange_shared_legend <- function(..., nrow = 1, ncol = length(list(...)), position = c("bottom", "right")) {
plots <- list(...)
position <- match.arg(position)
g <- ggplotGrob(plots[[1]] + theme(legend.position = position))$grobs
legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
lheight <- sum(legend$height)
lwidth <- sum(legend$width)
gl <- lapply(plots, function(x) x + theme(legend.position = "none"))
gl <- c(gl, nrow = nrow, ncol = ncol)
combined <- switch(position,
"bottom" = arrangeGrob(do.call(arrangeGrob, gl),
legend,
ncol = 1,
heights = unit.c(unit(1, "npc") - lheight, lheight)),
"right" = arrangeGrob(do.call(arrangeGrob, gl),
legend,
ncol = 2,
widths = unit.c(unit(1, "npc") - lwidth, lwidth)))
grid.newpage()
grid.draw(combined)
}
grid_arrange_shared_legend(men1, men2, women1, women2, nrow = 2, ncol = 2)
This is what the code came out with which is exactly what I want but it needs to have a 'Men' and 'Women' title:
Please help!! :)
I have tried using various different methods to be able to create one combined legend for my 4 ggplots, however, either it causes one of the graphs to be squished as compared to the other because the legend is within that plot area or it errors.
Here is a reproducible data set to work with and code for my graphs:
var=c("White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian","White", "Black", "Asian")
gender=c("Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women","Men","Women")
p=c(25, 35, 45, 26, 57, 43,35, 45, 43, 36, 27, 53,23, 55, 25, 25, 37, 23)
n=c(50, 100, 96, 57, 56, 54,50, 90, 96, 57, 56, 54,60, 110, 66, 37, 56, 54)
year=c(2019,2019,2019,2019,2019,2019, 2020,2020,2020,2020,2020,2020,2021,2021,2021,2021,2021,2021)
df=data.frame(year,var,gender,n,p)
df$var=factor(df$var, levels=c("Black","Asian","White"))
df$year=factor(df$year, levels=c(2019, 2020, 2021))
# Create graphs for men
men1=ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 150)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Number diagnosed")
men2=ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 100)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed")
# Combine graphs
men_combined=ggarrange(men1, men2,
nrow=1, ncol=2
)
# Add title to figure
men_combined=annotate_figure(men_combined,
top = text_grob("\nMen",
color = "black", face = "bold", size = 25))
# Create graphs for women
women1=ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 150)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Number diagnosed")
women2=ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 100)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
legend.position="none",
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed")
# Combine graphs
women_combined=ggarrange(women1, women2,
nrow=1, ncol=2
)
# Add title to figure
women_combined=annotate_figure(women_combined,
top = text_grob("\nWomen",
color = "black", face = "bold", size = 25))
# Combine all together
all_plots=ggarrange(men_combined, women_combined,
nrow=2, ncol=1)`
I have tried using the following to help and I was able to get a common legend but it then did not work when I tried using annotate_figure as I need to have a title above each to show the gender. Add a common Legend for combined ggplots
This is code I used which then did not work when I added the 'Men' and 'Women' titles:
grid_arrange_shared_legend <- function(..., nrow = 1, ncol = length(list(...)), position = c("bottom", "right")) {
plots <- list(...)
position <- match.arg(position)
g <- ggplotGrob(plots[[1]] + theme(legend.position = position))$grobs
legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
lheight <- sum(legend$height)
lwidth <- sum(legend$width)
gl <- lapply(plots, function(x) x + theme(legend.position = "none"))
gl <- c(gl, nrow = nrow, ncol = ncol)
combined <- switch(position,
"bottom" = arrangeGrob(do.call(arrangeGrob, gl),
legend,
ncol = 1,
heights = unit.c(unit(1, "npc") - lheight, lheight)),
"right" = arrangeGrob(do.call(arrangeGrob, gl),
legend,
ncol = 2,
widths = unit.c(unit(1, "npc") - lwidth, lwidth)))
grid.newpage()
grid.draw(combined)
}
grid_arrange_shared_legend(men1, men2, women1, women2, nrow = 2, ncol = 2)
This is what the code came out with which is exactly what I want but it needs to have a 'Men' and 'Women' title:
Please help!! :)
Share Improve this question asked Nov 21, 2024 at 20:04 Vicki LathamVicki Latham 674 bronze badges2 Answers
Reset to default 2Instead of creating and combining 4 individual plots, you could use a facet_
function to create small multiples. I'm using ggh4x::facet_grid2
specifically to get independent y-axis scales. To more directly answer the question, I also include an approach for collecting legends with patchwork
below.
library(dplyr)
library(tidyr)
library(ggh4x)
#> Loading required package: ggplot2
df |>
pivot_longer(cols = c(n, p)) |>
ggplot(aes(x = year, y = value, group = var, colour = var)) +
geom_line() +
facet_grid2(gender ~ name,
independent = "y",
scales = "free_y",
labeller = labeller(name = c(n = "Number diagnosed",
p = "Proportion diagnosed"))) +
labs(colour = "") +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)),
legend.position = "bottom",
strip.background = element_blank())
library(ggplot2)
library(patchwork)
# Create graphs for men
men1 <- ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 150)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Number diagnosed", title = "Men")
men2 <- ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 100)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed", title = "Men")
# Create graphs for women
women1 <- ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 150)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Number diagnosed", title = "Women")
women2 <- ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
scale_y_continuous(expand = expansion(mult = c(0, .06)), limits = c(0, 100)) +
theme(text=element_text(size=12),
axis.text = element_text(size=12),
axis.title = element_text(size=12, face="bold"),
axis.line.y=element_blank(),
plot.title.position="plot",
plot.subtitle=element_text(size=12, face="bold", margin = margin(b = 2)))+
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed", title = "Women")
men1 + men2 + women1 + women2 + plot_layout(guides = 'collect')
Created on 2024-11-21 with reprex v2.1.1
You can use patchwork::wrap_elements
like this
library(patchwork)
library(dplyr)
library(ggplot2)
men1=ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
labs(x = NULL, y = NULL, subtitle = "Number diagnosed") +
theme(legend.position = 'none')
men2=ggplot(data=df %>% filter(gender=="Men"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed") +
theme(legend.position = 'none')
women1=ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=n,group=var, colour=var))+
geom_line() +
labs(x = NULL, y = NULL, subtitle = "Number diagnosed") +
theme(legend.position = 'none')
women2=ggplot(data=df %>% filter(gender=="Women"), aes(x=year,y=p,group=var, colour=var))+
geom_line() +
labs(x = NULL, y = NULL, subtitle = "Proportion diagnosed")
men_plot = men1 + men2 + plot_annotation(subtitle = 'Men')
women_plot = women1 + women2 + plot_annotation(subtitle = 'Women') + plot_layout(guides = 'collect') & theme(legend.position = 'bottom')
wrap_elements(men_plot)/ wrap_elements(women_plot)
Created on 2024-11-21 with reprex v2.1.1
本文标签: rCombining ggplots and creating one combined legendStack Overflow
版权声明:本文标题:r - Combining ggplots and creating one combined legend - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736307485a1933328.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论