如何合并ggplot2绘制的3个柱状图为可区分的单个图形?
问题描述
我想把3个用ggplot2的geom_bar()创建的图形合并成单个图形,但position = "dodge"无法在每个X轴类别(X1、X2、X3…)处区分它们。patchwork包帮不上忙,因为这不是把图形拼到同一画布,而是合并图形;而merge只适用于数据框合并。
附上数据:
id = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3), reponse = c("12_vsys", "13_vsys", "14_vsys", "15_vsys", "16_vsys", "17_vsys", "18_vsys", "19_vsys", "20_vsys", "21_vsys", "22_vsys", "23_vsys", "24_vsys", "24_vsys", "12_vsys", "13_vsys", "14_vsys", "15_vsys", "16_vsys", "17_vsys", "18_vsys"), inf_palu2 = c("0", NA, NA, NA, NA, NA, "0", NA, NA, NA, NA, NA, "0", NA, "0", NA, NA, NA, NA, NA, "2"), inf_sympto2 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "1")), d2 <- data.frame(id, reponse, inf_palu2, inf_sympto2)
绘图代码:
library(ggplot2) ggplot() + geom_bar(d2, mapping = aes(x = reponse), position = "dodge", color = "blue") + geom_bar(d2,mapping = aes(x = reponse, fill = inf_palu2),position = "dodge", color = "red") + geom_bar(d2,mapping = aes(x = reponse, fill = inf_sympto2),position = "dodge", color = "yellow")
解决方案
直接叠加三个geom_bar图层会导致柱子重叠,因为每个图层独立基于原始数据绘制,没有明确的分组变量让position = "dodge"生效。正确做法是先将数据转换为长格式(tidy data),把inf_palu2和inf_sympto2合并成一个分类变量,再以此作为区分依据绘图。
步骤1:转换数据格式
加载tidyr包(未安装先运行install.packages("tidyr")),将宽格式数据转为长格式,并去除NA值:
library(tidyr) d2_long <- d2 %>% pivot_longer(cols = c(inf_palu2, inf_sympto2), names_to = "group", values_to = "value") %>% drop_na(value)
步骤2:绘制合并后的柱状图
用整理好的长数据绘图,通过group变量区分系列,position = "dodge"即可正常工作:
library(ggplot2) ggplot(d2_long, aes(x = reponse, fill = group)) + geom_bar(position = "dodge", color = "black") + scale_fill_manual(values = c("inf_palu2" = "red", "inf_sympto2" = "yellow")) + labs(title = "合并后的柱状图", x = "Reponse", y = "计数", fill = "分组")
可选:包含总计数的合并图
如果需要保留原代码中蓝色的总计数柱子,可先计算每个reponse的总计数,再合并到长数据中:
library(dplyr) # 计算总计数 total_counts <- d2 %>% count(reponse, name = "total") %>% mutate(group = "total", value = as.character(total)) # 合并总计数与分组数据 d2_combined <- bind_rows(d2_long, total_counts) # 绘制包含总计数的图形 ggplot(d2_combined, aes(x = reponse, fill = group)) + geom_bar(position = "dodge", color = "black") + scale_fill_manual(values = c("total" = "blue", "inf_palu2" = "red", "inf_sympto2" = "yellow")) + labs(title = "包含总计数的合并柱状图", x = "Reponse", y = "计数", fill = "分组")
内容的提问来源于stack exchange,提问作者Pipas
相关产品推荐
相关产品推荐

