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

R语言环形图添加箱线图及解决跨年连续性问题

R环形图中箱线图的环形连续性解决方案

问题背景

需要在R的环形时间线图中添加箱线图,核心痛点:12月与1月在环形逻辑上相邻,但现有箱线图会绕整个圆环延伸,无法体现二者的连续性。此前将年度起始设为9月的方法仅适用于特定数据集,需通用可靠方案。

核心原因

当前用yday(event_date) %% 365 / 365生成的day_of_year_shifted是线性0-1区间,12月对应接近1的值,1月对应接近0的值。箱线图基于线性区间计算统计量,会把这两个端点视为最远的两端,导致箱线图跨圆环显示。

通用解决方案

通过数据扩展+坐标截断实现环形连续性:

  • 复制一份数据集,将所有日期的x值(day_of_year_shifted)加1,模拟"下一年"的同月份数据
  • 用扩展后的数据集绘制箱线图,让箱线图能同时覆盖0-1和1-2区间的分布
  • 限制x轴显示范围为0-1,截断1-2区间的冗余元素,只保留环形交界处的连续箱线图部分

修改后的完整代码

# 加载必要库
library(ggplot2)
library(dplyr)
library(tidyr)
library(lubridate)
library(geomtextpath)

# 初始数据集:观测、孵化、产卵日期
df <- data.frame(
  date = as.Date(c("2019-01-08", "2023-01-18", "2023-01-18", "2024-01-21", 
                   "2018-12-30", "2023-03-31", "2023-12-27", "2024-02-24")),
  location = c("Obs1", "Obs2", "Obs3", "Obs4", "Obs5", "Obs6", "Obs7", "Obs8")
)

# 计算孵化和产卵日期
df <- df %>%
  mutate(
    hatching_date = date - weeks(5),
    egg_laying_date = hatching_date - weeks(4)
  )

# 转换为长格式,计算环形坐标
df_long <- df %>%
  pivot_longer(cols = c(date, hatching_date, egg_laying_date), 
               names_to = "date_type", values_to = "event_date") %>%
  mutate(
    month_shifted = (month(event_date) - 1) %% 12 + 1,
    day_of_year_shifted = yday(event_date) / 365,  # 无需取模,后续通过扩展数据处理环形
    y_offset = case_when(
      date_type == "date" ~ 1,
      date_type == "hatching_date" ~ 0.85,
      date_type == "egg_laying_date" ~ 0.75
    )
  )

# 扩展数据集:复制一份并偏移x值,处理环形连续性
df_long_extended <- bind_rows(
  df_long,
  df_long %>% mutate(day_of_year_shifted = day_of_year_shifted + 1)
)

# 绘制环形图
ggplot() +
  # 月份标签(仅显示0-1区间)
  geom_textpath(data = data.frame(x = seq(0.5/13, 12.5/13, length.out = 12), 
                                  y = 1.1, label = month.abb),
                aes(x, y, label = label), size = 5, color = "darkgrey") +
  # 月份分割线(仅显示0-1区间)
  geom_segment(data = data.frame(x = seq(0, 11) / 12, xend = seq(0, 11) / 12,
                                 y = 0.55, yend = 1.15),
               aes(x = x, y = y, xend = xend, yend = yend), color = "grey50", linetype = "dashed") +
  # 事件点(仅用原数据,避免重复)
  geom_point(data = df_long, aes(x = day_of_year_shifted, y = y_offset, color = date_type), size = 3) +
  # 观测点标签(仅用原数据)
  geom_text(data = df_long %>% filter(date_type == "date"), aes(x = day_of_year_shifted, y = 1.2, label = location), size = 3) +
  # 箱线图(用扩展后的数据,确保环形连续性)
  geom_boxplot(data = df_long_extended, aes(x = day_of_year_shifted, y = y_offset, fill = date_type, group = date_type),
               width = 0.05, alpha = 0.3, outlier.shape = NA) +
  # 颜色自定义
  scale_color_manual(values = c(date = "red", hatching_date = "blue", egg_laying_date = "green")) +
  scale_fill_manual(values = c(date = "red", hatching_date = "blue", egg_laying_date = "green")) +
  # 极坐标+限制x轴范围,截断冗余部分
  coord_polar(xlim = c(0, 1)) +
  # 主题调整
  theme_void() +
  labs(title = "环形时间线(1月置顶)", color = "日期类型", fill = "日期类型") +
  theme(legend.position = "right")

效果说明

修改后,12月与1月的箱线图会在环形交界处自然衔接,不会跨圆环延伸。该方案无需手动调整年度起始月,适用于任何全年分布的数据集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:32:01