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

使用ggplot2的geom_col绘制分组条形图时柱子高度一致问题排查

分组条形图柱子高度一致的问题解决

问题描述

想要绘制各柱子高度不同的分组条形图,但当前代码生成的条形图所有柱子高度一致。使用geom_col作为绘图函数,但不清楚问题出在哪里。

原代码:

# Add a new column to indicate age group
young$age_group <- "Young"
old$age_group <- "Old"

# Combine the data frames
combined_df <- bind_rows(young, old)

# Plot
ggplot(combined_df, aes(x = age_group, y = implvdm, fill = gndr)) +
  geom_col(position = "dodge") +
  labs(x = "Age Group", y = "implvdm", fill = "Gender") +
  theme_minimal()

示例数据:

young <- structure(list(gndr = c("woman", "man", "man", "man", "woman", 
"man", "man", "woman", "woman", "man"), yrbrn = c(2003L, 1999L, 
1998L, 1999L, 2002L, 1999L, 2001L, 2004L, 2004L, 1999L), agea = c(18L, 
22L, 23L, 22L, 19L, 22L, 21L, 17L, 18L, 22L), impdema = c(6L, 
6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), implvdm = c(10L, 7L, 9L, 
7L, 10L, 10L, 9L, 10L, 8L, 10L), accalaw = c(0L, 2L, 1L, 0L, 
5L, 3L, 3L, 0L, 2L, 0L), imwbcnt = c(9L, 2L, 7L, 4L, 0L, 10L, 
2L, 3L, 7L, 6L), euftf = c(4L, 3L, 7L, 4L, 6L, 5L, 8L, 5L, 5L, 
9L), freehms = c(1L, 3L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L), gincdif = c(2L, 
3L, 2L, 3L, 2L, 3L, 2L, 3L, 2L, 3L), prtclffi = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_)), row.names = c(NA, 
-10L), class = "data.frame")

old <- structure(list(gndr = c("man", "woman", "woman", "man", "woman", 
"man", "woman", "woman", "woman", "woman"), yrbrn = c(1943L, 
1975L, 1974L, 1977L, 1959L, 1993L, 1990L, 1993L, 1958L, 1971L
), agea = c(78L, 46L, 47L, 44L, 63L, 27L, 31L, 29L, 63L, 50L), 
    impdema = c(6L, 6L, 6L, 5L, 6L, 6L, 6L, 3L, 6L, 1L), implvdm = c(10L, 
    9L, 9L, 6L, 8L, 10L, 4L, 8L, 9L, 10L), accalaw = c(0L, 8L, 
    2L, 2L, 2L, 0L, 3L, 3L, 9L, 0L), imwbcnt = c(9L, 1L, 3L, 
    3L, 5L, 5L, 7L, 4L, 3L, 7L), euftf = c(8L, 2L, 4L, 3L, 4L, 
    3L, 7L, 5L, 4L, 5L), freehms = c(2L, 2L, 4L, 2L, 2L, 1L, 
    4L, 2L, 4L, 1L), gincdif = c(2L, 2L, 2L, 3L, 2L, 4L, 1L, 
    2L, 2L, 3L), prtclffi = c(NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_)), row.names = c(NA, -10L), class = "data.frame")

原因分析

geom_col(stat = "identity")默认会将同一分组(age_group + gndr)下的所有implvdm数值累加,最终柱子高度是该组的总和。如果数据中各组总和恰好相近,就会出现柱子高度几乎一致的情况。而你想要的应该是每个分组的汇总统计值(比如均值、中位数),或是每个个体的条形按分组独立展示。

解决方案

方案1:先汇总数据再绘图

使用dplyr对数据按age_group和gndr分组,计算所需的统计量(这里以均值为例),再用geom_col绘图:

library(dplyr)
library(ggplot2)

# 数据分组汇总(计算均值)
summary_df <- combined_df %>%
  group_by(age_group, gndr) %>%
  summarise(mean_implvdm = mean(implvdm), .groups = "drop")

# 绘制分组条形图
ggplot(summary_df, aes(x = age_group, y = mean_implvdm, fill = gndr)) +
  geom_col(position = "dodge") +
  labs(x = "年龄组", y = "implvdm均值", fill = "性别") +
  theme_minimal()

方案2:用stat_summary直接在绘图时计算统计量

无需提前汇总数据,直接在ggplot中使用stat_summary计算并绘制统计量:

ggplot(combined_df, aes(x = age_group, y = implvdm, fill = gndr)) +
  stat_summary(fun = mean, geom = "col", position = "dodge") +
  labs(x = "年龄组", y = "implvdm均值", fill = "性别") +
  theme_minimal()

方案3:展示每个个体的条形(若需要)

如果想要展示每个样本的数据,而非汇总值,可以添加group参数确保每个个体条形独立展示:

ggplot(combined_df, aes(x = age_group, y = implvdm, fill = gndr, group = interaction(age_group, gndr))) +
  geom_col(position = position_dodge(width = 0.9)) +
  labs(x = "年龄组", y = "implvdm", fill = "性别") +
  theme_minimal()

结果说明

方案1和方案2会生成每个年龄组内男女各一个柱子,高度为对应分组的均值(可替换为median、sum等其他统计量),满足"各柱子高度不同"的分组条形图效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:24:49