如何用ggplot绘制总和的中位数线?附现有代码求优化建议
如何用ggplot绘制总和的中位数线(附代码修正)
首先,我先帮你梳理现有代码的问题,然后给出符合需求的解决方案:
核心问题分析
你的代码里有几个关键问题导致无法正常生成想要的图表:
- 没有将日期转换为月份分组:你用了
aes(Month, n)但数据里根本没有Month列,ggplot会直接报错; stat_summary的参数过时:fun.y在新版ggplot2中已经被弃用,应该改用fun;- 冗余的日期类型转换:把
Date转成POSIXlt没必要,ggplot对原生Date类型支持更好; - 缺少分组设置:如果按月份聚合,需要指定
group=1才能让线连续连接。
解决方案:两种常见的"总和中位数线"场景
根据你的描述,我假设你需要两种情况之一,下面分别给出代码:
场景1:每月总计数的线 + 所有月份总计数的中位数水平线
这种场景是先计算每个月的总count,然后添加一条水平线表示所有月份总count的中位数:
library(tidyverse) library(lubridate) library(scales) # 1. 简化日期处理 dataset$Created_Date <- gsub("T.*", "", dataset$Created_Date) dataset$Created_Date <- ymd(dataset$Created_Date) # 直接用ymd解析,无需strptime # 2. 重命名列(用dplyr的rename_with更简洁) dataset <- dataset %>% rename_with(~gsub(" ", "_", .x)) # 3. 统计每日count dfcount <- dataset %>% count(Created_Date) # 4. 计算所有月份总count的中位数(先聚合再取中位数) monthly_totals <- dfcount %>% group_by(month = floor_date(Created_Date, "month")) %>% summarise(total = sum(n)) %>% pull(total) median_total <- median(monthly_totals) # 5. 绘制图表 Monthlywithavg <- ggplot(dfcount, aes(x = floor_date(Created_Date, "month"), y = n)) + # 按月求和的线(蓝色) stat_summary(fun = sum, geom = "line", color = "#1f77b4", size = 1, aes(group = 1)) + # 中位数水平线(红色虚线) geom_hline(yintercept = median_total, color = "#ff4b5c", linetype = "dashed", size = 1) + # x轴格式化:显示年月,每月一个刻度 scale_x_date(labels = date_format("%Y-%m"), breaks = "1 month") + # 图表标签 labs(x = "Month", y = "Total Daily Count", title = "Monthly Total Count with Overall Median Line") + # 美化主题,避免x轴标签重叠 theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) Monthlywithavg
场景2:每月总计数的线 + 每月内每日count的中位数线
这种场景是同时展示每月的总count,以及每个月内每日count的中位数趋势:
# 沿用前面的数据处理步骤,直接绘制图表 Monthlywithavg <- ggplot(dfcount, aes(x = floor_date(Created_Date, "month"), y = n)) + # 按月求和的线(蓝色) stat_summary(fun = sum, geom = "line", color = "#1f77b4", size = 1, aes(group = 1)) + # 每月内每日count的中位数线(绿色) stat_summary(fun = median, geom = "line", color = "#2ca02c", size = 1, aes(group = 1)) + scale_x_date(labels = date_format("%Y-%m"), breaks = "1 month") + labs(x = "Month", y = "Count", title = "Monthly Total Count vs Daily Median Count", caption = "Blue: Monthly Total | Green: Daily Median per Month") + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) Monthlywithavg
其他需要修改的细节
- 日期处理简化:你原来的
ymd(strptime(...))可以直接改成ymd(dataset$Created_Date),因为ymd函数能直接识别%Y-%m-%d格式的字符串; - 列重命名优化:用
rename_with比直接修改names(dataset)更符合tidyverse风格,也更稳健; - x轴标签可读性:添加
theme(axis.text.x = element_text(angle = 45, hjust = 1))可以避免月份标签重叠; - 避免警告:新版ggplot2中
fun.y已经被弃用,必须改用fun,否则会弹出警告信息。
内容的提问来源于stack exchange,提问作者Archie
相关产品推荐
相关产品推荐

