如何用ggplot2将多组斑块比例关联图合并为单张复合图?
问题需求
需要用一段代码生成一组关联图:
- X轴:年龄(
H2_lft) - Y轴:斑块存在人群的比例
- 每个子图对应一个研究变量:种族(
H1_EtnTotaal)、性别(H1_geslacht)、吸烟状态(H2_Roken)、高血压(Hypertension)
目前能单独绘制每张图,但无法合并为多子图的复合图。之前绘制IMT指标时使用的tidyr::pivot_longer方法,在这个斑块比例场景下无法生效。
现有单独绘图代码
A <- Dataset %>% group_by(H2_lft, H1_EtnTotaal) %>% summarise(p = mean(Plaque_presence == "Yes")) %>% ggplot(aes(x = H2_lft, y = p, fill = H1_EtnTotaal)) + scale_fill_discrete(name = "Ethnicity") + geom_smooth(se = TRUE) + scale_y_continuous(limits = c(0, 1)) + theme_classic() A + labs(x = "Age (years)", y = "Proportion of plaque", title = "Plaque presence", caption = "Figure 2: Proportion of participants with plaque") + theme(plot.title = element_text(hjust = 0.5)) B <- Dataset %>% group_by(H2_lft, H1_geslacht) %>% summarise(p = mean(Plaque_presence == "Yes")) %>% ggplot(aes(x = H2_lft, y = p, fill = H1_geslacht)) + scale_fill_discrete(name = "Sex") + geom_smooth(se = TRUE) + scale_y_continuous(limits = c(0, 1)) + theme_classic() B + labs(x = "Age (years)", y = "Proportion of plaque", title = "Plaque presence", caption = "Figure 2: Proportion of participants with plaque") + theme(plot.title = element_text(hjust = 0.5)) C <- Dataset %>% group_by(H2_lft, H2_Roken) %>% summarise(p = mean(Plaque_presence == "Yes")) %>% ggplot(aes(x = H2_lft, y = p, fill = H2_Roken)) + scale_fill_discrete(name = "Smoking") + geom_smooth(se = TRUE) + scale_y_continuous(limits = c(0, 1)) + theme_classic() C + labs(x = "Age (years)", y = "Proportion of plaque", title = "Plaque presence", caption = "Figure 2: Proportion of participants with plaque") + theme(plot.title = element_text(hjust = 0.5)) D <- Dataset %>% group_by(H2_lft, Hypertension) %>% summarise(p = mean(Plaque_presence == "Yes")) %>% ggplot(aes(x = H2_lft, y = p, fill = Hypertension)) + scale_fill_discrete(name = "Hypertension") + geom_smooth(se = TRUE) + scale_y_continuous(limits = c(0, 1)) + theme_classic() D + labs(x = "Age (years)", y = "Proportion of plaque", title = "Plaque presence", caption = "Figure 2: Proportion of participants with plaque") + theme(plot.title = element_text(hjust = 0.5))
此前IMT图合并代码
new <- tidyr::pivot_longer(Dataset, c(H1_EtnTotaal, H2_Roken, H1_geslacht, Diabetes_GLUC_MED)) ggplot(new, aes(H2_lft, MeanIMT_alg, group = value)) + geom_smooth( data = ~ subset(.x, name == "H1_EtnTotaal"), aes(colour = value), se = TRUE ) + scale_colour_discrete(name = "Ethnicity") + new_scale_colour() + geom_smooth( data = ~ subset(.x, name == "H1_geslacht"), aes(colour = value), se = TRUE ) + scale_colour_discrete(name = "Sex") + new_scale_colour() + geom_smooth( data = ~ subset(.x, name == "H2_Roken"), aes(colour = value), se = TRUE ) + scale_colour_discrete(name = "Smoking") + new_scale_colour() + geom_smooth( data = ~ subset(.x, name == "Diabetes_GLUC_MED"), aes(colour = value), se = TRUE ) + scale_colour_discrete(name = "Diabetes") + new_scale_colour() + geom_smooth( method = lm, se = TRUE, aes(group = NULL) ) + facet_wrap(~ name) + theme_classic() + theme(plot.title = element_text(hjust = 0.5)) + labs(x = "Age (years)", y = "Mean IMT (mm)", title ="IMT", caption = "Figure 2: association between cardiovascular risk factors and IMT", color = "cardiovascular risk factors", fil = "cardiovascular risk factors")
解决方案
核心思路是先把数据整理成长格式,同时保留Plaque_presence列,再按年龄、分组变量计算斑块比例,最后用facet_wrap生成多子图,避免重复代码且统一控制样式。
完整合并代码
library(tidyverse) # 1. 将分组变量转成长格式,保留年龄和斑块状态 Dataset_long <- Dataset %>% select(H2_lft, Plaque_presence, H1_EtnTotaal, H1_geslacht, H2_Roken, Hypertension) %>% pivot_longer(cols = -c(H2_lft, Plaque_presence), names_to = "group_var", values_to = "group_value") # 2. 计算每个年龄、分组下的斑块比例 Dataset_summary <- Dataset_long %>% group_by(H2_lft, group_var, group_value) %>% summarise(p = mean(Plaque_presence == "Yes"), .groups = "drop") # 3. 绘制多子图复合图 ggplot(Dataset_summary, aes(x = H2_lft, y = p, fill = group_value)) + geom_smooth(se = TRUE) + # 为每个子图设置对应图例标题 scale_fill_discrete(name = function() { current_var <- ggplot_build(.)$layout$facet$params$rows[[1]] case_when( current_var == "H1_EtnTotaal" ~ "Ethnicity", current_var == "H1_geslacht" ~ "Sex", current_var == "H2_Roken" ~ "Smoking", current_var == "Hypertension" ~ "Hypertension" ) }) + scale_y_continuous(limits = c(0, 1)) + # 按分组变量分面 facet_wrap(~ group_var, scales = "free") + # 统一设置标签和主题 labs(x = "Age (years)", y = "Proportion of plaque", title = "Plaque presence by demographic and clinical factors", caption = "Figure 2: Proportion of participants with plaque") + theme_classic() + theme(plot.title = element_text(hjust = 0.5), strip.text = element_text(size = 10))
代码说明
- 数据整理:用
pivot_longer把多个分组变量转换为group_var(变量名)和group_value(变量取值)两列,同时保留年龄和斑块状态数据。 - 比例计算:按年龄、分组变量、分组值分组,计算每组的斑块存在比例。
- 绘图设置:
facet_wrap(~ group_var)自动生成对应每个研究变量的子图- 用
scale_fill_discrete结合case_when为每个子图匹配对应的图例标题 - 统一控制Y轴范围、主题和标签,减少重复代码
内容的提问来源于stack exchange,提问作者Marleen
相关产品推荐
相关产品推荐

