如何用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") )
关键说明
- 类别统一:必须把类似的类别名称标准化,比如原数据中的"Respiratory traits"和"Respiratory diseases"、"Anthropometrics"和"Anthropometric measurements"都统一成同一个名称,否则图例会显示重复条目;
- 颜色映射:通过
scale_fill_brewer指定breaks=all_traits,确保所有类别都被纳入颜色映射,即使某个饼图没有该类别,图例也会显示; - 分面设置:用
facet_wrap实现多饼图布局,nrow=2控制行数,让布局更美观; - 标签位置:按分组计算
csum和pos,确保每个饼图的百分比标签位置正确。
内容的提问来源于stack exchange,提问作者Jessica
相关产品推荐
相关产品推荐

