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

如何合并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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:17:11