双月滑动窗口最大值提取:无需天数参数的实现方法
精确提取双月滑动窗口内日度时序数据最大值的方法
问题背景
有2020-01-01至2021-12-31的日度时间序列数据,需要提取连续双月滑动窗口(如1-2月、2-3月…11-12月)内的最大值。原方法用slider::slide_index_dbl固定前后30天计算,因不同月份天数差异导致结果不精确,最终输出需匹配MEI指数的格式(双月标识+对应月份1日的日期)。
解决方案
方法一:基于月份分组的精确计算
这种方法直接按双月窗口分组,自动适配不同月份的天数,结果完全精确。
1. 为日度数据标记双月窗口信息
用lubridate提取年月,给每个日期分配对应的双月窗口标签、基准日期(匹配MEI的Date字段)以及窗口的时间范围:
library(tidyverse) library(lubridate) set.seed(333) df <- data.frame( date = seq(as.Date('2020-01-01'), as.Date('2021-12-31'), '1 day'), value = round(rnorm(731,100,33)) ) df_with_window <- df %>% mutate( year = year(date), month = month(date), # 生成MEI格式的双月标签 window_label = case_when( month == 1 ~ "DJ", month == 2 ~ "JF", month == 3 ~ "FM", month == 4 ~ "MA", month == 5 ~ "AM", month == 6 ~ "MJ", month == 7 ~ "JJ", month == 8 ~ "JA", month == 9 ~ "AS", month == 10 ~ "SO", month == 11 ~ "ON", month == 12 ~ "ND" ), # 窗口对应的基准日期(和MEI的Date字段一致) window_date = ymd(paste(year, month, "01", sep = "-")), # 确定窗口的起始和结束日期 window_start = case_when( window_label == "DJ" ~ ymd(paste(year - 1, "12", "01", sep = "-")), TRUE ~ ymd(paste(year, month - 1, "01", sep = "-")) ), window_end = ceiling_date(window_date, "month") - days(1) )
2. 按窗口分组计算最大值
two_month_max <- df_with_window %>% group_by(window_date, window_label, year) %>% summarise(two_month_max = max(value, na.rm = TRUE), .groups = "drop") %>% rename(Month = window_label, Date = window_date, Year = year) %>% select(Year, Month, Date, two_month_max) # 查看结果示例 head(two_month_max)
3. 与MEI数据合并
library(rsoi) mei <- download_mei() # 通过Year、Month、Date三个字段匹配合并 mei_with_max <- mei %>% left_join(two_month_max, by = c("Year", "Month", "Date")) # 查看合并后的数据 head(mei_with_max)
方法二:用slider包基于月份偏移定义窗口
如果想继续使用slider包,可以直接用月份偏移代替固定天数,自动适配不同月份的天数:
library(slider) df %>% mutate( # 窗口范围:当前日期所在月的前一个月第一天,到当前日期所在月的最后一天 two_month_max = slide_index_dbl( value, date, ~max(.x, na.rm = TRUE), .before = months(1), # 前推1个月 .after = days(0), # 包含当前月所有天数 .complete = TRUE # 仅返回完整窗口的结果 ) ) %>% filter(day(date) == 1) %>% # 保留每月1日的数据,匹配MEI基准日期 mutate( Month = case_when( month(date) == 1 ~ "DJ", month(date) == 2 ~ "JF", month(date) == 3 ~ "FM", month(date) == 4 ~ "MA", month(date) == 5 ~ "AM", month(date) == 6 ~ "MJ", month(date) == 7 ~ "JJ", month(date) == 8 ~ "JA", month(date) == 9 ~ "AS", month(date) == 10 ~ "SO", month(date) == 11 ~ "ON", month(date) == 12 ~ "ND" ), Year = year(date) ) %>% select(Year, Month, Date = date, two_month_max)
这种方法无需手动设置天数,months(1)会自动识别前一个月的实际天数,保证窗口范围精确对应连续双月。
内容的提问来源于stack exchange,提问作者tassones
相关产品推荐
相关产品推荐

