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

基于geom_segment()的排序日历图优化:分段排序与刻度修复

ggplot2日历图调整方案

问题需求

用ggplot2制作日历图时,需完成两项调整:

  • 每个year与num_months分组的分面内,geom_segment按start_month从小到大排序,分面中第一个分段对应最小的start_month,依次排列;
  • 强制每个年份的x轴刻度范围固定为当年1月至12月,即使该时间段无观测数据。

修改后的完整代码

library(tidyverse)
library(lubridate)

data <- read_csv("num_months,start_month_year,end_month_year,B1,B1_p,year,start_month,end_month
1,6,6,3.3571016788482666,0.007681768853217363,2021,5,5
1,8,8,2.548985481262207,0.007373321335762739,2021,7,7
1,10,10,2.139772415161133,0.03452971577644348,2021,9,9
1,12,12,2.165775775909424,0.07796278595924377,2021,11,11
1,13,13,1.9506219625473022,0.09215697646141052,2021,12,12
1,23,23,2.7839596271514893,0.011407249607145786,2022,10,10
1,25,25,2.220555543899536,0.06181173026561737,2022,12,12
6,6,11,0.9881601333618164,0.08719704300165176,2021,5,10
6,8,13,1.438501238822937,0.032221969217061996,2021,7,12
6,9,14,1.16400945186615,0.09187468141317368,2021,8,1
6,10,15,1.5834165811538696,0.03494146466255188,2021,9,2
6,11,16,1.294316291809082,0.09792502969503403,2021,10,3
6,12,17,1.4204859733581543,0.0546354204416275,2021,11,4
6,20,25,1.07038414478302,0.0722803920507431,2022,7,12") %>%
  mutate(
    start_dt = ymd(paste(year, start_month, "01", sep = "-")),
    end_dt = case_when(
      # 处理跨年份的结束日期
      start_month > end_month ~ ceiling_date(ymd(paste(year + 1, end_month, "01", sep = "-")), unit = "month") - 1,
      TRUE ~ ceiling_date(ymd(paste(year, end_month, "01", sep = "-")), unit = "month") - 1
    )
  ) %>%
  # 分组内按start_month升序排序,确保y轴位置正确
  group_by(year, num_months) %>%
  arrange(start_month, .by_group = TRUE) %>%
  mutate(yy = row_number()) %>%
  ungroup()

# 绘制日历图
ggplot(data) +
  geom_segment(aes(x = start_dt, xend = end_dt, y = yy, yend = yy, color = factor(num_months)), size = 1) +
  scale_x_date(
    date_labels = "%b",
    date_breaks = "1 month",
    expand = expansion(0, 0),
    # 强制每个分面x轴为当年1月1日至12月31日
    limits = function(x) {
      current_year = year(x)[1]
      ymd(c(paste0(current_year, "-01-01"), paste0(current_year, "-12-31")))
    }
  ) +
  scale_y_continuous(labels = NULL) +
  # x轴不使用自由刻度,只放开y轴
  facet_grid(rows = vars(num_months), cols = vars(year), space = "free_y", scales = "free_y") +
  labs(x = "月份", y = "月份数量", color = "月份数量") +
  theme_bw() +
  theme(
    panel.spacing = unit(1, "lines"),
    panel.grid.major.y = element_blank(),
    axis.ticks.y = element_blank()
  )

调整说明

1. 分面内segment排序修正

  • 改为分组内再次按start_month升序排序(arrange(start_month, .by_group = TRUE)),确保每个分面内的yy严格对应start_month从小到大的顺序,避免全局排序被后续操作干扰。
  • 简化了start_dt的生成逻辑,无需用case_when区分年份,直接拼接即可。

2. 固定x轴范围为全年

  • 将facet_grid的scales参数从"free"改为"free_y",保留y轴自由刻度的同时,固定x轴规则。
  • 在scale_x_date中添加limits函数,自动识别每个分面对应的年份,将x轴范围强制设为当年1月1日至12月31日,确保无数据的月份也会显示刻度。
  • 修正了跨年份的end_dt计算逻辑,当start_month > end_month时(比如起始月为8月、结束月为1月),自动对应到下一年的结束日期,避免日期计算错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:32:05