CalendR配置:如何可视化同一天的冲突事件?
问题分析与解决方案
核心问题原因
你遇到的问题本质是calendR的special.days参数限制:它接受的是一个长度等于当年天数的向量,每个日期位置只能存储单个事件值,后续的赋值会直接覆盖之前的内容。比如1月2日(第2天)先被赋值为Fish Tales,之后又被赋值为Marlin,最终向量中该位置的值是Marlin,所以只会显示对应的绿色底色。
calendR是否支持拆分单元格?
calendR本身没有内置的日期单元格横向/纵向拆分功能来显示多事件底色,但可以借助其底层依赖的ggplot2进行自定义扩展,实现类似效果。
实现多事件底色拆分的具体方法
以下是基于ggplot2图层扩展的解决方案,以横向拆分单元格为例:
- 重构事件数据
首先将事件整理为数据框,保留每个日期的所有事件记录,避免覆盖:
library(tidyverse) library(calendR) library(viridis) library(scales) # 重构事件数据为数据框 events_df <- tibble( day = c(3,22,45,63,100,140,195,234,300, 2,36,59,123,167,210,289,340, 2,25,80,155,255,297,339, 1,89,92,142,143,239,360,361), event = c(rep("Big Catch",9), rep("Fish Tales",8), rep("Marlin",7), rep("Holiday",8)) ) # 标记存在多事件的日期 multi_event_days <- events_df %>% count(day) %>% filter(n > 1) %>% pull(day)
- 绘制基础日历并扩展图层
先绘制无特殊底色的基础日历,再通过ggplot2的geom_tile和geom_rect分别添加单事件底色和多事件拆分底色:
# 绘制基础日历框架 p <- calendR(year = 2024, start = "M", lty = 1, bg.col = "white", subtitle.col = 1, weeknames = c("M", "T", "W", "T", "F", "S", "S"), day.size = 3.5, orientation = "l", legend.pos = "bottom", special.days = NULL # 先不设置默认特殊日期 ) # 获取日历的坐标数据 cal_data <- p$data # 合并事件数据与日历坐标 cal_data_with_events <- cal_data %>% left_join(events_df, by = "day") # 定义事件与颜色的映射 color_map <- c( "Big Catch" = "#3b528bff", "Fish Tales" = "#21908cff", "Marlin" = "#5dc863ff", "Holiday" = "lightgray" ) # 添加单事件日期的底色 single_event_data <- cal_data_with_events %>% filter(!day %in% multi_event_days) %>% drop_na(event) p <- p + geom_tile(data = single_event_data, aes(fill = event), inherit.aes = FALSE, alpha = 1) # 处理多事件日期,生成横向拆分的色块坐标 multi_event_data <- cal_data_with_events %>% filter(day %in% multi_event_days) %>% drop_na(event) %>% group_by(day) %>% mutate( n_events = n(), x_min = x + (row_number() - 1)/n_events, x_max = x + row_number()/n_events ) %>% ungroup() # 添加多事件拆分的底色 p <- p + geom_rect(data = multi_event_data, aes(xmin = x_min, xmax = x_max, ymin = y, ymax = y + 1, fill = event), inherit.aes = FALSE, alpha = 1) + scale_fill_manual(values = color_map) + guides(fill = guide_legend(title = "船只出海记录")) # 输出最终日历 print(p)
纵向拆分的调整
如果需要纵向拆分单元格,只需修改多事件数据的坐标计算部分,将x轴偏移改为y轴偏移:
multi_event_data <- cal_data_with_events %>% filter(day %in% multi_event_days) %>% drop_na(event) %>% group_by(day) %>% mutate( n_events = n(), y_min = y + (row_number() - 1)/n_events, y_max = y + row_number()/n_events ) %>% ungroup() # 对应的geom_rect参数调整 p <- p + geom_rect(data = multi_event_data, aes(xmin = x, xmax = x + 1, ymin = y_min, ymax = y_max, fill = event), inherit.aes = FALSE, alpha = 1)
内容的提问来源于stack exchange,提问作者Tuna-92
相关产品推荐
相关产品推荐

