使用ggplot2绘制分组面积图,是否需重构R语言中的DataFrame?
ggplot分组面积图的数据结构问题
问题描述
我是用ggplot做数据可视化的新手,现在要画一张面积图:x轴是Days,y轴是Spend,按Person A和Person B分组。手里的DataFrame是宽格式的,结构如下:
df<-data.frame(Days=c(1,2,3,4,5,6,7), PersonASpend=c(100,0,90,20,5,8,10), PersonBSpend=c(30,20,120,20,55,20,0))
对应的表格结构:
| Days | PersonASpend | PersonBSpend |
|---|---|---|
| 1 | 100 | 30 |
| 2 | 0 | 20 |
| 3 | 90 | 120 |
| 4 | 20 | 20 |
| 5 | 5 | 55 |
| 6 | 8 | 20 |
| 7 | 10 | 0 |
想请教:是不是必须把它转换成下面这种仅含一个Spend指标的长格式?有没有其他实现方式?
长格式示例:
| Days | Person | Spend |
|---|---|---|
| 1 | A | 100 |
| 2 | A | 0 |
| 3 | A | 90 |
| ... | ... | ... |
| 1 | B | 30 |
| 2 | B | 20 |
| ... | ... | ... |
解答
结论:优先转成长格式
这是ggplot官方推荐的整洁数据格式——一个变量对应一列,这样ggplot的语法能更顺畅地工作,代码也更简洁易维护。
1. 如何转换长格式
用tidyverse包的pivot_longer函数一步就能完成:
library(tidyverse) # 转换长格式并清理Person列的名称 df_long <- df %>% pivot_longer( cols = c(PersonASpend, PersonBSpend), # 指定要转换的列 names_to = "Person", # 新分组列的名称 values_to = "Spend" # 数值列的名称 ) %>% mutate(Person = str_replace(Person, "Person(.)Spend", "\\1")) # 把PersonASpend简化为A,PersonBSpend简化为B
2. 用长格式绘制面积图
转换后直接调用ggplot,代码逻辑清晰:
ggplot(df_long, aes(x = Days, y = Spend, fill = Person)) + geom_area(alpha = 0.7, position = "stack") + # stack为堆叠面积图,换成position="fill"可生成百分比堆叠图 labs(title = "每日支出面积图", x = "天数", y = "支出", fill = "人员") + theme_minimal()
3. 不转格式的替代方法(不推荐)
确实可以不用转格式,手动给每个分组添加geom_area,但这种方式代码冗余、扩展性差——如果后续要新增Person C,就得额外再写一行geom_area,图例也需要手动配置:
ggplot(df, aes(x = Days)) + geom_area(aes(y = PersonASpend, fill = "A"), alpha = 0.7) + geom_area(aes(y = PersonBSpend, fill = "B"), alpha = 0.7) + scale_fill_manual(values = c("A" = "#2ecc71", "B" = "#3498db")) + labs(y = "Spend", fill = "Person")
总结
转成长格式是最优解,完全贴合ggplot的设计逻辑,不管是调整分组、修改样式还是后续扩展,都比宽格式的写法高效得多。
内容的提问来源于stack exchange,提问作者locket
相关产品推荐
相关产品推荐

