如何使用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
相关产品推荐
相关产品推荐

