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

如何在带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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:25:32