如何用R绘制按城市分组的n、y列求和条形图并添加数值标签?
解决分组求和双条形图的问题
看起来你遇到的核心问题有两个:一是聚合数据时的列名大小写不匹配(原始数据列是city,你代码里用了City),导致缺失城市;二是绘图时的映射逻辑错误,把数值列当成了填充变量,而不是先把宽格式数据转成长格式。
下面是完整的修正步骤:
1. 先确保数据列名一致,正确聚合求和
首先,R是严格区分大小写的,你的原始数据列名是小写的city,但之前用aggregate(. ~ City, ...)时用了大写City,这会导致聚合时找不到正确的分组列,自然丢失数据。
可以用两种方式完成聚合:
方式一:基础R的aggregate函数
# 假设你的原始数据对象名为raw_data sum_data <- aggregate(cbind(n, y) ~ city, data = raw_data, FUN = sum)
执行后会得到每个城市n和y的总和,列名保持city、n、y。
方式二:用dplyr(更直观易读)
如果你已经安装了dplyr包,这种链式写法逻辑更清晰:
library(dplyr) sum_data <- raw_data %>% group_by(city) %>% summarize(total_n = sum(n), total_y = sum(y)) %>% ungroup()
2. 将聚合后的宽格式数据转成长格式
ggplot绘制分组条形图需要长格式数据(每一行对应一个「城市-数据类型-总和」的组合),所以需要转换数据结构:
# 用reshape2包的melt函数 library(reshape2) sum_data_long <- melt(sum_data, id.vars = "city", variable.name = "type", value.name = "total") # 或者用tidyr包的pivot_longer(tidyverse生态推荐) library(tidyr) sum_data_long <- sum_data %>% pivot_longer(cols = c(n, y), names_to = "type", values_to = "total")
转换后的数据结构会是这样:
| city | type | total |
|---|---|---|
| mon | n | 120 |
| mon | y | 276 |
| tor | n | 259 |
| tor | y | 396 |
| edm | n | 160 |
| edm | y | 114 |
3. 绘制带数值标签的分组条形图
现在用ggplot绘制,同时给每个条形添加上方的求和数值标签:
library(ggplot2) ggplot(sum_data_long, aes(x = city, y = total, fill = type)) + geom_bar(stat = "identity", position = position_dodge(width = 0.9)) + # 添加数值标签,位置和条形对齐 geom_text(aes(label = total), position = position_dodge(width = 0.9), vjust = -0.5, size = 4) + labs(title = "各城市n和y的总和对比", x = "城市", y = "总和", fill = "数据类型") + theme_minimal()
为什么你之前的绘图不符合预期?
你之前写的ggplot(sum_data,aes(x = City,y = n)) + geom_bar(aes(fill = y),stat = "identity",position = "dodge"),错误在于fill = y是把y列的数值作为填充颜色的变量,所以会出现颜色渐变效果,而不是把y作为一个与n并列的类别。只有把数据转成长格式,用专门的列(比如这里的type)来区分n和y,才能用fill = type实现分组条形的效果。
内容的提问来源于stack exchange,提问作者dysonsphere
相关产品推荐
相关产品推荐

