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

如何在ggplot2的geom_histogram中使同fill类别子组堆叠展示?

问题描述

我想要创建一个直方图,使用数据集的一列作为填充色(fill),另一列作为分组(group),两者均在aes()中定义,并为每个组添加白色边框,且组的数量多于填充类别。

问题在于,定义group后,同一fill类别下的子组并未在条形中堆叠在一起,而是呈现随机排列。尝试在传入ggplot()前按fill列对data.frame排序,但并未解决问题。

需求:即使子组不同、x轴日期不同,同一fill类别的观测仍能堆叠在一起。

示例数据

# Set seed for reproducibility:
set.seed(123)

# Set start date:
start_date <- as.Date("2024-01-01")

# Set end date:
end_date <- as.Date("2024-04-01")

# Create data.frame:
data <- data.frame(
  onset_date = sample(seq(start_date, end_date, by = "day"), 
                      100, 
                      replace = TRUE),
  category = sample(c("A", "B"), 
                    100, 
                    replace = TRUE))

# Add row names for grouping:
data$grouping <- as.numeric(row.names(data))

# Create epicurve_breaks
epicurve_breaks <- seq.Date(
  from = start_date, 
  to = end_date, 
  by = "week")

问题现象

  • 无分组的直方图(geom_histogram仅设置fill = category):同一fill类别的元素会正常堆叠。
  • 添加group = grouping后的直方图:category A和B的区块随机分散,无法聚集。
解决方法

核心原因是直接设置group = grouping会将每一行视为独立分组,打乱了ggplot默认按fill堆叠的逻辑。要实现同类别子组聚集+每个子组带白色边框,推荐先预处理数据,再用geom_bar替代geom_histogram,具体如下:

步骤1:预处理数据

先将日期映射到指定的周区间,同时按区间和类别排序,确保同类别子组排列在一起:

library(dplyr)
library(ggplot2)

# 为每条数据分配对应的周区间
data$interval <- cut(data$onset_date, breaks = epicurve_breaks, 
                     closed = "left", include.lowest = TRUE)

# 按区间、类别排序,保证同类别子组在堆叠时聚集
data_sorted <- data %>% 
  arrange(interval, category, grouping)

步骤2:绘制堆叠直方图

使用geom_bar的position = "stack"参数,结合排序后的数据实现需求:

p3 <- ggplot(data_sorted, aes(x = interval, fill = category, group = grouping)) +
  geom_bar(position = "stack", colour = "white") +
  # 简化x轴日期标签,只显示起始日期
  scale_x_discrete(labels = function(x) substr(x, 1, 10)) +
  labs(x = "Onset Date")

print(p3)

替代方案(用geom_histogram实现)

如果坚持使用geom_histogram,可以将group设置为interaction(category, grouping),同时确保数据按category排序,让同类别子组优先聚合:

# 先按category排序
data_sorted <- data %>% arrange(category)

p4 <- ggplot(data_sorted, aes(x = onset_date, fill = category, 
                              group = interaction(category, grouping))) +
  geom_histogram(breaks = epicurve_breaks, closed = 'left', colour = "white")

print(p4)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:30:59