按Class-Area组统计各事件对应上一及前冬历史事件数
按Class和Area分组统计事件前两个冬季的同组事件数
需求说明
为数据集中的每个事件,按class与area组成的分组,统计该事件发生前,上一个冬季(12、1、2月)以及再前一个冬季内发生的同组事件数量。
示例数据集
class <- c(1,1,1,1,1,2,2,2,2) area <- c("a", "a","b", "a", "a","b", "a", "a","b" ) event <- as.Date(c("2023-04-01", "2022-12-01", "2022-01-01", "2021-12-01", "2022-12-01", "2022-12-01", "2020-04-01", "2022-04-01", "2022-04-01")) df <- data.frame(class, area, event) %>% arrange(class, area, event) # 按分组和日期排序 # 用户期望的结果列 df$events_in_previous_winter <- c(0,1,1,2,0,0,0,0,0) df
解决方案(dplyr实现)
这里用冬季结束年份作为标识,通过向量操作实现高效统计,适配85000条数据的规模:
library(dplyr) library(lubridate) # 1. 为每个事件标记所属的冬季ID(冬季定义为每年12月至次年2月,用冬季结束年份作为ID) df_result <- df %>% mutate( winter_id = case_when( month(event) <= 2 ~ year(event), # 1-2月属于当年结束的冬季 TRUE ~ year(event) + 1 # 3-12月属于下一年结束的冬季 ) ) %>% # 2. 按class和area分组 group_by(class, area) %>% # 3. 统计前两个冬季的同组事件数:winter_id为当前ID-1和ID-2,且事件发生在当前事件之前 mutate( events_in_previous_winter = sum(winter_id %in% c(winter_id - 1, winter_id - 2) & event < event) ) %>% # 4. 移除临时列并取消分组 ungroup() %>% select(-winter_id) # 查看结果 df_result
逻辑说明
- 冬季ID标记:把每个事件映射到对应的冬季结束年份,比如2021-12-01属于2022冬季(结束于2022年2月),2022-01-01也属于2022冬季。
- 分组统计:在每个
class+area组内,对每个事件,统计组内所有满足以下条件的事件数:- 所属冬季是当前事件冬季的前两个(
winter_id = 当前ID-1和当前ID-2) - 事件日期早于当前事件(确保是发生在当前事件之前的)
- 所属冬季是当前事件冬季的前两个(
这个方法全程用向量操作,比逐行计算效率高很多,适合处理大数据量。
内容的提问来源于stack exchange,提问作者threeisles
相关产品推荐
相关产品推荐

