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

如何使用geom_bar绘制非堆叠多系列,实现收入栏内嵌费用与边际贡献

哈哈,这个需求我太熟了!之前也纠结过怎么不用手动算差值就能做出这种内嵌的条形图,其实用tidyverse+ggplot2的组合就能轻松搞定,完全符合Hadley的设计思路~

首先,你之前遇到的堆叠问题,应该是把收入、费用、边际贡献三个指标都当成独立系列扔进geom_bar里了,结果它们的数值直接相加,肯定不是你要的效果。咱们要的是收入作为整个条形的总高度,费用和边际贡献是它的两个内部组成部分,核心是把数据整理成「每个年份对应两个类别(费用、边际贡献)」的长格式,而不是把三个指标都列成宽格式。

不用手动算差值也没关系,用一行mutate就能自动算出边际贡献,然后转成长格式就行。给你举个具体的例子:

假设你的数据框是这样的(宽格式):

df <- tibble(
  year = 2018:2022,
  revenue = c(50000, 62000, 75000, 68000, 82000),
  expense = c(32000, 38000, 45000, 42000, 48000)
)

然后用下面的代码就能画出你要的图:

library(tidyverse)

df %>%
  # 自动计算边际贡献,不用手动算!
  mutate(contribution_margin = revenue - expense) %>%
  # 把宽格式转成长格式,方便ggplot处理
  pivot_longer(
    cols = c(expense, contribution_margin),
    names_to = "category",
    values_to = "amount"
  ) %>%
  ggplot(aes(x = year, y = amount, fill = category)) +
  # 用geom_col(等价于geom_bar(stat="identity"))做堆叠条形图
  geom_col(position = "stack") +
  # 调整标签和颜色,让图表更直观
  labs(
    x = "年份",
    y = "金额(美元)",
    title = "年度收入、费用及边际贡献",
    fill = "类别"
  ) +
  scale_fill_manual(
    values = c("expense" = "#636363", "contribution_margin" = "#3182bd"),
    labels = c("费用", "边际贡献")
  ) +
  theme_minimal()

这样画出来的图,每个条形的总高度就是当年的收入,内部的深色部分是费用,浅色部分是边际贡献,完全符合你的需求。而且整个过程没有手动算差值,都是代码自动处理,非常高效~

另外,如果你不想提前计算边际贡献,其实也可以用geom_rect的方法,但那个需要手动调整条形的宽度,不如上面的方法简洁。所以还是推荐用tidy数据的思路,这也是ggplot2设计的核心思想,Hadley肯定是希望咱们这么用的😉

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:03:30