如何基于衰减函数计算R中不规则间隔时间序列的加权滚动30日和
不规则时间序列的前30天加权滚动和计算
这个问题我刚好碰见过类似的,不规则时间序列的加权滚动计算确实不能直接用常规的固定窗口滚动函数,得基于时间范围来动态筛选每个观测对应的窗口。下面给你两种可行的实现方法,按需选择就好:
方法一:用tidyverse(dplyr + purrr)实现(直观易读)
这种方法代码逻辑清晰,适合数据量不大的场景,新手也容易理解:
首先先生成可复现的测试数据(记得加set.seed保证结果一致):
set.seed(123) df <- data.frame(date = as.Date("2016-01-01") + ((1:100) + sample(1:5, 100, replace = TRUE)), data = rnorm(100))
先把数据按日期排序,避免时间乱序导致窗口筛选错误:
library(dplyr) df <- df %>% arrange(date)
定义题目里的衰减参数和函数:
tau <- 0.05 decay <- function(tau, day) { exp(-tau * day) }
最后计算加权滚动和:
library(purrr) df <- df %>% mutate( weighted_rolling_sum = map_dbl(date, function(current_date) { # 筛选当前日期前30天内的所有观测(包含当天) window_data <- filter(df, date >= current_date - 30, date <= current_date) # 计算每个观测的权重:day是当前日期与窗口内日期的间隔天数 weights <- decay(tau, as.numeric(current_date - window_data$date)) # 计算data与权重的乘积之和 sum(window_data$data * weights) }) )
方法二:用data.table实现(高效版)
如果你的数据量很大(比如几十万甚至上百万行),tidyverse的循环方法速度会比较慢,这时候推荐用data.table的非等连接,效率提升非常明显:
library(data.table) set.seed(123) dt <- data.table(date = as.Date("2016-01-01") + ((1:100) + sample(1:5, 100, replace = TRUE)), data = rnorm(100)) # 按日期排序 setorder(dt, date) tau <- 0.05 decay <- function(tau, day) { exp(-tau * day) } # 非等连接实现动态窗口加权求和 dt[, weighted_rolling_sum := dt[.(lower = date - 30, upper = date), on = .(date >= lower, date <= upper), sum(data * decay(tau, as.numeric(upper - date))), by = .EACHI]$V1]
关键逻辑说明
不管用哪种方法,核心都是:
- 对每个观测的日期,找到该日期往前30天到当天的所有数据(因为是不规则时间序列,每个窗口的观测数量不一样)
- 权重计算:当日数据的间隔天数为0,权重
exp(-0.05*0)=1;30天前的数据间隔天数为30,权重exp(-0.05*30)≈0.2231,完全符合题目要求 - 最后计算窗口内
data × 权重的总和,就是我们要的加权滚动和
内容的提问来源于stack exchange,提问作者Bobby
相关产品推荐
相关产品推荐

