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

求助:用ggplot绘制按acquiYear分组的直方图及密度曲线

R语言实现:按年份分组绘制带密度曲线的条形图

需求说明

针对数据表dt,实现以下可视化需求:

  • 按acquiYear(获取年份)分组,每个年份下的month(月份)对应一个条形,条形高度为nrOrders(订单数量)
  • 为每个年份添加一条跨月份的订单数量密度曲线
  • 指定年份颜色:#00943C(2014)、#4A52A0(2015)、#FDC300(2016)、#6F6F6F(2017)、#EC4C24(2018)

数据表结构

structure(list(acquiYear = c("2014", "2014", "2014", "2014", "2014", "2014", 
"2014", "2014", "2014", "2014", "2014", "2014", "2015", "2015", 
"2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", 
"2015", "2015", "2016", "2016", "2016", "2016", "2016", "2016", 
"2016", "2016", "2016", "2016", "2016", "2016", "2017", "2017", 
"2017", "2017", "2017", "2017", "2017", "2017", "2017", "2017", 
"2017", "2017", "2018", "2018", "2018", "2018", "2018", "2018", 
"2018", "2018", "2018", "2018", "2018", "2018"), month = structure(c(1L, 2L, 3L, 4L, 
5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 
8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 
11L, 12L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 
1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L), .Label = c("Jan", 
"Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", 
"Nov", "Dec"), class = "factor"), nrOrders = c(0, 0, 0, 0, 0, 
0, 0, 0, 1, 1, 2, 0, 2, 4, 5, 3, 7, 3, 5, 4, 3, 7, 8, 7, 2, 24, 
16, 33, 9, 27, 16, 10, 27, 9, 31, 35, 11, 11, 25, 15, 18, 19, 
19, 8, 27, 34, 43, 51, 0, 11, 2, 0, 0, 0, 0, 0, 4, 5, 1, 0), 
    ), row.names = c(NA, -60L), class = c("data.table", 
"data.frame"))

实现代码

我们使用ggplot2包完成可视化,同时利用data.table处理数据结构:

# 加载依赖包
library(ggplot2)
library(data.table)

# 定义年份对应颜色
year_colors <- c("#00943C", "#4A52A0", "#FDC300", "#6F6F6F", "#EC4C24")
names(year_colors) <- unique(dt$acquiYear) # 绑定颜色与年份

# 绘制分面式可视化(每个年份单独面板,更清晰)
ggplot(dt, aes(x = month)) +
  # 绘制月份订单条形图
  geom_col(aes(y = nrOrders, fill = acquiYear), width = 0.7, show.legend = FALSE) +
  # 添加密度曲线:将月份转为数值计算密度,缩放y轴匹配订单数量范围
  stat_density(aes(x = as.numeric(month), y = ..density.. * max(dt$nrOrders), color = acquiYear),
               geom = "line", size = 1, show.legend = FALSE) +
  # 按年份分面
  facet_wrap(~acquiYear, ncol = 2) +
  # 设置填充色与曲线颜色
  scale_fill_manual(values = year_colors) +
  scale_color_manual(values = year_colors) +
  # 添加右侧密度轴,便于观察密度趋势
  scale_y_continuous(sec.axis = sec_axis(~./max(dt$nrOrders), name = "订单密度")) +
  # 设置坐标轴标签
  labs(x = "月份", y = "订单数量") +
  # 调整主题样式
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    strip.text = element_text(size = 10, face = "bold", color = year_colors)
  )

代码说明

  1. 颜色绑定:将指定颜色与年份一一对应,确保可视化风格统一
  2. 条形图绘制:每个月份对应一个条形,高度为订单数量,填充色为对应年份颜色
  3. 密度曲线:将离散的月份转为数值型,计算订单数量的核密度估计,通过缩放密度值使其与订单数量的y轴范围匹配,便于同时观察绝对值与分布趋势
  4. 分面布局:每个年份单独一个面板,避免不同年份的数据拥挤重叠
  5. 双y轴:右侧添加密度轴,清晰展示订单数量在各月份的分布密度

备选:分组条形图(同一面板展示所有年份)

如果需要在同一个面板展示所有年份的条形与曲线,可使用以下代码:

ggplot(dt, aes(x = month)) +
  # 分组条形图,按年份错开排列
  geom_col(aes(y = nrOrders, fill = acquiYear), 
           position = position_dodge(width = 0.8), width = 0.7) +
  # 分组密度曲线,与条形对齐
  stat_density(data = dt, 
               aes(x = as.numeric(month), y = ..density.. * max(dt$nrOrders), 
                   color = acquiYear, group = acquiYear),
               geom = "line", size = 1, position = position_dodge(width = 0.8)) +
  # 设置颜色
  scale_fill_manual(values = year_colors, name = "获取年份") +
  scale_color_manual(values = year_colors, name = "获取年份") +
  labs(x = "月份", y = "订单数量") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

内容的提问来源于stack exchange,提问作者Miko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 01:14:50