You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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))

代码说明

  1. 数据整理:用pivot_longer把多个分组变量转换为group_var(变量名)和group_value(变量取值)两列,同时保留年龄和斑块状态数据。
  2. 比例计算:按年龄、分组变量、分组值分组,计算每组的斑块存在比例。
  3. 绘图设置:
    • facet_wrap(~ group_var)自动生成对应每个研究变量的子图
    • 用scale_fill_discrete结合case_when为每个子图匹配对应的图例标题
    • 统一控制Y轴范围、主题和标签,减少重复代码

内容的提问来源于stack exchange,提问作者Marleen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:35:19