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

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))

错误分析与修正方案

问题所在

  1. 柱状条重叠:直接调用两个geom_bar会让两组柱子在同一x坐标位置重叠,无法实现并列效果。
  2. geom_text无有效映射:未指定数据源和映射关系,无法正确显示柱子的数值标签。
  3. 无法生成图例: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 08:07:00