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

ggplot2横向分组柱状图:固定图层顺序与按组归一化至100%

解决ggplot2横向分组柱状图的两个问题

你在用R的ggplot2绘制横向分组柱状图时遇到两个问题:

  • 分组内的柱子会根据数值大小自动排序,需要固定FTP(蓝色)在前、CTP(红色)在后的显示顺序
  • 当前是全局数值归一化,需要改为按每个avenue组将数值归一化至100%

1. 固定分组内柱子的顺序

ggplot默认会按因子水平(或字符字典序)排列分组,要固定FTP在前,只需把name列转为指定了水平顺序的因子,同时可以自定义对应颜色确保符合需求。

2. 按avenue组归一化到100%

之前的代码是对所有avenue的数值全局求和计算百分比,现在要改成每个avenue内部求和后计算占比,用dplyr的分组计算可以高效完成。


修改后的完整代码

library(ggplot2)
library(tidyverse)

# 保留指定小数位数的函数
specify_decimal <- function(x, k) trimws(format(round(x, k), nsmall = k))

# 示例数据
avenues <- c("Avenue1", "Avenue2", "Avenue3", "Avenue4")
flytip_amount <- c(1000, 2000, 1500, 250)
collection_amount <- c(5, 15, 10, 2000)

df <- data.frame(avenues, flytip_amount, collection_amount)

# 数据处理:转成长格式 + 按avenue组计算百分比
df_processed <- df %>%
  # 转成长格式,直接将原始列映射为FTP/CTP
  pivot_longer(
    cols = -avenues,
    names_to = "name",
    values_to = "amount",
    names_transform = list(name = ~case_when(
      .x == "flytip_amount" ~ "FTP",
      .x == "collection_amount" ~ "CTP"
    ))
  ) %>%
  # 按每个avenue分组计算
  group_by(avenues) %>%
  mutate(
    total = sum(amount),
    value = (amount / total) * 100,
    value = specify_decimal(value, 1) %>% as.numeric() # 转为数值型方便绘图
  ) %>%
  ungroup() %>%
  # 强制固定分组顺序:FTP在前,CTP在后
  mutate(name = factor(name, levels = c("FTP", "CTP")))

# 绘制图表
ggplot(df_processed, aes(x = avenues, fill = name, y = value)) +
  geom_col(position = "dodge", width = 0.75) +
  coord_flip() +
  # 自定义颜色:FTP蓝色,CTP红色
  scale_fill_manual(values = c("FTP" = "#1f77b4", "CTP" = "#ff4b5c")) +
  labs(
    title = "Flytipping & Collection %",
    x = "ward_name",
    y = "Percentage per ward"
  ) +
  # 让文本和柱子对齐,避免重叠
  geom_text(
    aes(label = paste0(value, "%")),
    position = position_dodge(width = 0.75),
    vjust = -0.5,
    size = 5
  ) +
  # 调整y轴范围,防止百分比文本超出图表
  ylim(0, 110)

关键修改说明

  • 用pivot_longer直接完成数据格式转换和命名,减少冗余中间数据框
  • group_by(avenues) + mutate(total = sum(amount))实现按组求和归一化
  • mutate(name = factor(name, levels = c("FTP", "CTP")))强制固定分组显示顺序
  • scale_fill_manual指定颜色,确保FTP和CTP的颜色符合需求
  • position_dodge(width = 0.75)让标签和对应柱子对齐,避免文本重叠

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:40:50