如何在带facet_grid的ggplot时间序列图中高亮工作日?
如何在ggplot分面时间序列图中高亮工作日
首先,咱们先修正你代码里的一个关键问题:日期处理错误。你用的洗发水销售数据集里,Month字段是「年份-月份」格式(比如1-01代表第1年1月),不是「日-月」,所以之前的日期转换逻辑会导致工作日判断完全错误。先把这个问题解决,再谈高亮的事。
步骤1:正确处理数据并标记工作日
首先加载必要的包,修正日期解析,同时标记每个日期是否为工作日(周一至周五):
library(tidyverse) library(lubridate) # 更方便的日期处理工具 # 读取并清洗数据 data <- read_csv("shampoo.csv") %>% # 拆分年份和月份(原Month是"年度-月份"格式) separate(Month, into = c("year_num", "month"), sep = "-", convert = TRUE) %>% mutate( # 设定起始年份为2018(可根据需求调整) year = 2018 + year_num - 1, # 转换为每月第一天的日期 date = ymd(paste(year, month, "01", sep = "-")), # 获取星期几 week_day = weekdays(date), # 标记是否为工作日(周一至周五) is_weekday = week_day %in% c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday") )
步骤2:分面图中高亮工作日
根据你用facet_grid按星期几和月份分面的需求,有两种常用的高亮方式:
方式1:给工作日分面添加背景色
如果想让所有属于工作日的分面(周一至周五的面板)整体高亮,可以用geom_rect绘制分面背景,只在工作日的面板显示:
data %>% ggplot(aes(date, Sales, group = 1)) + # 先绘制工作日分面的背景(浅蓝半透明) geom_rect( data = . %>% filter(is_weekday), aes(xmin = min(date), xmax = max(date), ymin = -Inf, ymax = Inf), fill = "#e6f2ff", alpha = 0.3 ) + # 绘制销售趋势线 geom_line(color = "darkslateblue", linewidth = 0.8) + # 按星期几(行)和月份(列)分面 facet_grid(vars(week_day), vars(month)) + # 优化主题 theme_bw() + labs(x = "日期", y = "销售额")
方式2:给工作日的数据点/线条单独上色
如果只想突出显示工作日对应的销售数据(而非整个分面),可以直接用is_weekday变量映射颜色:
data %>% ggplot(aes(date, Sales, group = 1, color = is_weekday)) + geom_line(linewidth = 0.8) + # 自定义颜色:工作日用深蓝色,非工作日用灰色 scale_color_manual(values = c("TRUE" = "darkslateblue", "FALSE" = "gray60")) + facet_grid(vars(week_day), vars(month)) + theme_bw() + labs(x = "日期", y = "销售额", color = "是否工作日")
扩展:如果是每日数据的情况
如果你的实际数据是每日销售数据(而非月度),想在分面中高亮每个工作日的日期区域,可以先扩展数据为每日,再创建背景图层:
# 扩展月度数据为每日示例(实际使用时替换为你的每日数据) daily_data <- data %>% group_by(year, month) %>% summarise( date = seq(date, ymd(paste(year, month, days_in_month(date), sep = "-")), by = "day"), Sales = rep(Sales, days_in_month(date)) ) %>% ungroup() %>% mutate( week_day = weekdays(date), is_weekday = week_day %in% c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday"), month = format(date, "%m"), year = format(date, "%Y") ) # 创建每个分面的工作日背景数据 bg_data <- daily_data %>% group_by(year, month) %>% summarise( xmin = min(date), xmax = max(date), ymin = -Inf, ymax = Inf, is_weekday = any(is_weekday) ) # 绘图:分面中高亮工作日日期区域 daily_data %>% ggplot(aes(date, Sales, group = 1)) + geom_rect( data = filter(bg_data, is_weekday), aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), fill = "#f0f8ff", alpha = 0.2 ) + geom_line(aes(color = is_weekday), linewidth = 0.7) + scale_color_manual(values = c("TRUE" = "steelblue", "FALSE" = "gray50")) + facet_grid(vars(year), vars(month)) + theme_minimal()
这样就能完美实现分面下的工作日高亮效果啦!
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

