ggplot双数据框同变量分组柱状图绘制及图例设置求助
问题描述
我有两个变量结构完全一致的数据集data1和data2,仅count变量存在差异——data2的count筛选条件更严格。想绘制一张柱状图,每个月份旁并列两个柱状条,分别对应两个数据集的count值。尝试了以下代码但无法正常运行,请问哪里出错了?另外能否为图表手动创建图例?
附上尝试的代码:
ggplot() + geom_bar(data=data1, aes(x = as.Date(date), y = count), stat = "identity", fill="red") + geom_bar(data=data2, aes(x = as.Date(date), y = count), stat = "identity", fill="blue") + geom_text(vjust = -0.5, size = 3)+ labs(y= "Counts", x = "Date", title = "Results") + theme_classic()
数据集data1结构:
structure(list(year = c(2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023), month = c(4, 5, 6, 7, 8, 9, 10, 11, 12, 1), count = c(8, 9, 15, 14, 8, 9, 7, 14, 18, 10), date = structure(c(2022.25, 2022.33333333333, 2022.41666666667, 2022.5, 2022.58333333333, 2022.66666666667, 2022.75, 2022.83333333333, 2022.91666666667, 2023), class = "yearmon")), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L), groups = structure(list( year = c(2022, 2023), .rows = structure(list(1:9, 10L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))
数据集data2结构:
structure(list(year = c(2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023), month = c(4, 5, 6, 7, 8, 9, 10, 11, 12, 1), count = c(6, 5, 14, 12, 5, 7, 6, 15, 17, 9), date = structure(c(2022.25, 2022.33333333333, 2022.41666666667, 2022.5, 2022.58333333333, 2022.66666666667, 2022.75, 2022.83333333333, 2022.91666666667, 2023), class = "yearmon")), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L), groups = structure(list( year = c(2022, 2023), .rows = structure(list(1:9, 10L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))
错误分析与修正方案
问题所在
- 柱状条重叠:直接调用两个
geom_bar会让两组柱子在同一x坐标位置重叠,无法实现并列效果。 geom_text无有效映射:未指定数据源和映射关系,无法正确显示柱子的数值标签。- 无法生成图例:
fill参数写在aes()外部,ggplot无法识别分组逻辑,自然不会生成对应图例。
最优解决思路:合并为长格式数据集
ggplot更适配长格式数据,先给两个数据集添加分组标记再合并,即可用单一geom_bar实现并列柱子,同时自动生成图例。
修正后的代码
library(tidyverse) library(zoo) # 处理yearmon类型数据 # 添加分组标记并合并数据集 combined_data <- bind_rows( data1 %>% mutate(group = "宽松筛选"), data2 %>% mutate(group = "严格筛选") ) %>% ungroup() # 取消原数据集的分组属性,避免绘图冲突 # 绘制并列柱状图 ggplot(combined_data, aes(x = date, y = count, fill = group)) + geom_bar(stat = "identity", position = position_dodge(width = 0.9)) + # position_dodge实现柱子并列 geom_text(aes(label = count), position = position_dodge(width = 0.9), vjust = -0.5, size = 3) + labs(y = "计数", x = "日期", title = "不同筛选条件下的月度计数", fill = "筛选条件") + # 自定义图例标题 scale_fill_manual(values = c("宽松筛选" = "red", "严格筛选" = "blue")) + # 手动指定柱子颜色 theme_classic() + scale_x_yearmon(format = "%Y-%m") # 优化x轴日期显示格式
手动创建图例的补充方案
如果坚持不合并数据集,也可以通过将fill放入aes()内部实现手动图例控制,但这种方式较繁琐,不推荐:
library(ggplot2) library(zoo) ggplot() + geom_bar(data = data1, aes(x = date, y = count, fill = "宽松筛选"), stat = "identity", position = position_dodge(width = 0.9)) + geom_bar(data = data2, aes(x = date, y = count, fill = "严格筛选"), stat = "identity", position = position_dodge(width = 0.9)) + geom_text(data = data1, aes(x = date, y = count, label = count), position = position_dodge(width = 0.9), vjust = -0.5, size = 3) + geom_text(data = data2, aes(x = date, y = count, label = count), position = position_dodge(width = 0.9), vjust = -0.5, size = 3) + labs(y = "计数", x = "日期", title = "不同筛选条件下的月度计数", fill = "筛选条件") + scale_fill_manual(values = c("宽松筛选" = "red", "严格筛选" = "blue")) + theme_classic() + scale_x_yearmon(format = "%Y-%m")
这里将fill作为分组变量放入aes(),ggplot会自动识别并生成图例,再通过scale_fill_manual手动指定颜色和标签。
内容的提问来源于Stack Exchange,提问作者daviddupont
相关产品推荐
相关产品推荐

