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

双月滑动窗口最大值提取:无需天数参数的实现方法

精确提取双月滑动窗口内日度时序数据最大值的方法

问题背景

有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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:20:02