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

在R中用ggplot调整堆叠图的图例、颜色顺序并添加数据标签

ggplot堆叠图问题解决指南

问题描述

我有一个包含多周期数据的数据集df,结构如下:

histo_periodCitypercentparticipants
Jul 20 - Aug 20London50100
Jul 20 - Aug 20New York2040
Jul 20 - Aug 20Paris3060
Sep 22 - Oct 22London1050
Sep 22 - Oct 22New York60300
Sep 22 - Oct 22Paris30150
Nov 21 - Dec 21London4545
Nov 21 - Dec 21New York2525
Nov 21 - Dec 21Paris3030

绘制堆叠图时遇到三个核心问题:

  • 时间周期未按实际先后顺序展示
  • 颜色未匹配指定的colours_order序列
  • 城市的堆叠顺序、图例排序未遵循设定的city_order(Paris, London, New York),默认按字母排序

同时需要在每个条形顶部标注该周期的总参与者数量。

当前使用的代码:

city_order <- c("Paris", "London", "New York")

colours_order <- c("#297D96", "#68C7E6", "#9BBB59")

ggplot(df, aes(x=histo_period, y=percent, fill=City)) + 
    geom_bar(position = "fill", stat="identity") + 
    scale_fill_manual(values = setNames(colours_order, city_order)) +
    labs(x = "Year", y= "Percent", fill ="") + 
    theme_light() + 
    theme(axis.title.y = element_text(angle= 0), 
          legend.position = "top", 
          axis.line = element_line(size = 0, colour = "black"),
          panel.border = element_blank(),
          panel.background = element_rect(fill = "white"),
          panel.grid.major = element_blank(),
          panel.grid.minor = element_blank()) +
    scale_y_continuous(expand = c(0,0))

解决方案

1. 修正时间周期排序

histo_period默认是字符型,ggplot会按字母顺序排列。需要先提取周期起始日期并转换为可识别的日期格式,再将histo_period转为因子并保留时间顺序:

# 提取每个周期的起始日期并转为日期格式
df$period_start <- as.Date(paste0(substr(df$histo_period, 1, 5), "01"), format = "%b %y %d")
# 按起始日期排序后,将histo_period转为因子
df <- df[order(df$period_start), ]
df$histo_period <- factor(df$histo_period, levels = unique(df$histo_period))

2. 固定城市堆叠与图例顺序

将City列转为因子,指定city_order为层级,这样ggplot会严格遵循该顺序进行堆叠和图例展示:

df$City <- factor(df$City, levels = city_order)

3. 确保颜色与城市匹配

之前的scale_fill_manual已经通过setNames绑定了颜色与城市,只要City的因子层级正确,颜色会自动对应设定的colours_order。

4. 添加条形顶部总参与者数量

先计算每个周期的总参与者,再用geom_text在条形顶部(y=1位置,因使用position="fill",y轴为0-1比例)添加数值:

# 计算每个周期的总参与者
total_participants <- aggregate(participants ~ histo_period, df, sum)

完整代码

library(ggplot2)

city_order <- c("Paris", "London", "New York")
colours_order <- c("#297D96", "#68C7E6", "#9BBB59")

# 处理时间排序
df$period_start <- as.Date(paste0(substr(df$histo_period, 1, 5), "01"), format = "%b %y %d")
df <- df[order(df$period_start), ]
df$histo_period <- factor(df$histo_period, levels = unique(df$histo_period))

# 固定城市顺序
df$City <- factor(df$City, levels = city_order)

# 计算每个周期总参与者
total_participants <- aggregate(participants ~ histo_period, df, sum)

# 绘制堆叠图
ggplot(df, aes(x=histo_period, y=percent, fill=City)) + 
    geom_bar(position = "fill", stat="identity") + 
    scale_fill_manual(values = setNames(colours_order, city_order)) +
    # 添加顶部总人数文本,inherit.aes=FALSE避免继承原数据的y映射
    geom_text(data = total_participants, aes(x = histo_period, y = 1, label = participants), 
              vjust = -0.5, size = 4, inherit.aes = FALSE) +
    labs(x = "时间周期", y= "占比", fill ="") + 
    theme_light() + 
    theme(axis.title.y = element_text(angle= 0), 
          legend.position = "top", 
          axis.line = element_line(size = 0, colour = "black"),
          panel.border = element_blank(),
          panel.background = element_rect(fill = "white"),
          panel.grid.major = element_blank(),
          panel.grid.minor = element_blank()) +
    scale_y_continuous(expand = c(0,0), limits = c(0, 1.1))  # 扩展y轴范围,避免顶部文本被截断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:03:14