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

如何用ggplot将多幅饼图合并为单图并配置共享图例?

合并多类别不全一致的饼图并共享图例

问题

需要将4幅饼图合并为一个图形,使用包含所有类别的共享图例,但各饼图的类别不完全一致,常规方法无法实现。

解决方案

核心思路是统一类别命名+整合所有数据+分面绘制,具体步骤如下:

  • 统一相似类别的名称(比如"Respiratory diseases"和"Respiratory traits"本质是同一类,需合并命名),避免因名称细微差异被识别为不同类别;
  • 将所有数据整合到一个数据框,添加分组标记区分不同饼图;
  • 按分组计算标签位置,最后用分面功能绘制多个饼图,同时指定统一的颜色映射实现共享图例。

完整实现代码

library(tidyverse)
library(ggrepel)

# 数据整理:统一类别名称并整合所有数据集
# 数据集1:GDF11 in OpenTarget Genetics
df1 <- tibble(
  Plot = "GDF11 - OpenTarget Genetics",
  Traits = c("Respiratory diseases", "Thyroid diseases", "Anthropometric measurements", 
             "White blood cell counts", "Diabetes", "Cognitive and education related traits", 
             "Ocular traits", "Other traits"),
  counts = c(59,14,49,20,26,20,23,45),
  labels = c("23.05%", "5.47%", "19.14%", "7.81%", "10.16%", "7.81%", "8.98%", "17.58%")
)

# 数据集2:GDF11 in TWAS Hub
df2 <- tibble(
  Plot = "GDF11 - TWAS Hub",
  Traits = c("Respiratory diseases", "Thyroid diseases", "Anthropometric measurements", 
             "White blood cell counts", "Cognitive and education related traits", 
             "Cardiovascular traits", "Psychiatric traits", "Other traits"),
  counts = c(15, 2, 13, 2, 7, 5, 11, 11),
  labels = c("16.48%", "2.20%", "14.29%", "2.20%", "7.69%", "5.49%", "12.09%", "12.09%")
)

# 数据集3:MSTN in OpenTarget Genetics
df3 <- tibble(
  Plot = "MSTN - OpenTarget Genetics",
  Traits = c("Red blood cell traits", "Platelet counts", "Mineral levels/content", "Other traits"),
  counts = c(31, 6, 6, 12),
  labels = c("56.36%", "10.91%", "10.91%", "21.82%")
)

# 数据集4:MSTN in TWAS Hub
df4 <- tibble(
  Plot = "MSTN - TWAS Hub",
  Traits = c("Cardiovascular traits", "Respiratory diseases", "Thyroid diseases", 
             "Anthropometric measurements", "Other traits"),
  counts = c(7, 10, 2, 6, 7),
  labels = c("21.88%", "31.25%", "6.25%", "18.75%", "21.88%")
)

# 合并所有数据集
combined_df <- bind_rows(df1, df2, df3, df4)

# 计算每个分组的标签位置
combined_df2 <- combined_df %>%
  group_by(Plot) %>%
  mutate(csum = rev(cumsum(rev(counts))),
         pos = counts/2 + lead(csum, 1),
         pos = if_else(is.na(pos), counts/2, pos)) %>%
  ungroup()

# 获取所有唯一类别,用于统一颜色映射
all_traits <- unique(combined_df$Traits)

# 绘制分面饼图
ggplot(combined_df, aes(x="", y=counts, fill=Traits)) +
  geom_col(width=1, color=1) +
  coord_polar(theta="y") +
  # 指定统一颜色,确保所有类别都有对应颜色
  scale_fill_brewer(palette="Pastel2", breaks=all_traits) +
  # 分面,每个分组一个饼图
  facet_wrap(~Plot, nrow=2) +
  geom_label_repel(data=combined_df2, aes(y=pos, label=labels), 
                   size=3, nudge_x=1, show.legend=FALSE) +
  guides(fill=guide_legend(title="Traits", ncol=2)) +
  ggtitle("Significant associations with GDF11 and MSTN") +
  theme_void() +
  theme(
    plot.title = element_text(hjust=0.5, size=14, face="bold"),
    legend.title = element_text(size=12),
    legend.text = element_text(size=10),
    strip.text = element_text(size=11, face="italic")
  )

关键说明

  1. 类别统一:必须把类似的类别名称标准化,比如原数据中的"Respiratory traits"和"Respiratory diseases"、"Anthropometrics"和"Anthropometric measurements"都统一成同一个名称,否则图例会显示重复条目;
  2. 颜色映射:通过scale_fill_brewer指定breaks=all_traits,确保所有类别都被纳入颜色映射,即使某个饼图没有该类别,图例也会显示;
  3. 分面设置:用facet_wrap实现多饼图布局,nrow=2控制行数,让布局更美观;
  4. 标签位置:按分组计算csum和pos,确保每个饼图的百分比标签位置正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:05:12