基于rollapplyr实现时间序列DataFrame滚动窗口加权求和
解决xts/zoo时间序列的滚动窗口加权求和问题
我懂你想要做的事:给xts/zoo格式的时间序列每列做宽度为3的滚动加权求和,权重是tempWeights <- c(1.09, 0.89, 0),而且明确说了当日的观测值无权重、权重不需要归一化。你之前试着用rollapplyr搭配weighted.mean,但因为需要的是求和而非均值,所以得调整下实现方式。
正确的实现代码
直接在rollapplyr的自定义函数里手动计算加权求和就好,没必要用weighted.mean(它会自动除以权重和,这不是你要的)。另外要注意,rollapplyr默认是右对齐窗口——也就是每个窗口包含当前行和之前的2行,刚好匹配你的权重顺序(第一个权重对应窗口里最早的观测,最后一个0对应当日的观测):
# 先加载需要的包 library(xts) # 模拟一份xts格式的示例数据(代替你的tempVar) set.seed(123) tempVar <- xts(matrix(rnorm(9), ncol=3), order.by = as.Date("2024-01-01") + 0:2) colnames(tempVar) <- c("Col1", "Col2", "Col3") # 定义你的权重 tempWeights <- c(1.09, 0.89, 0) # 执行滚动加权求和 tempRRI <- rollapplyr(tempVar, width = 3, function(x) { # 把窗口内的矩阵和权重相乘,再按列求和 colSums(x * tempWeights) }, by.column = FALSE) # 设为FALSE直接处理整个矩阵,比逐列跑更高效
关键细节说明
- 窗口对齐逻辑:
rollapplyr的r后缀代表右对齐,每个窗口对应t-2、t-1、t三个时间点的观测,正好对应你权重里的1.09(t-2)、0.89(t-1)、0(t),完美契合你的需求。 - 加权求和的正确姿势:我们直接让窗口矩阵
x和权重向量相乘(R会自动按列广播权重),再用colSums算每列的加权和,这样就避开了weighted.mean自动归一化的问题。 - by.column参数:这里设为
FALSE是因为直接处理整个窗口矩阵效率更高;如果你习惯逐列处理,也可以改成by.column=TRUE,然后把函数写成function(x) sum(x * tempWeights),结果完全一样。
验证结果
用上面的示例数据运行后,tempRRI的输出会是这样(前两行因为窗口不够3个观测,自动填充NA):
tempRRI # Col1 Col2 Col3 # 2024-01-01 NA NA NA # 2024-01-02 NA NA NA # 2024-01-03 0.2033 -0.47328 -0.278616
这个结果就是每列按x[1]*1.09 + x[2]*0.89 + x[3]*0计算出来的,完全符合你的要求。
关于weighted.sum的小补充
其实R基础包里并没有weighted.sum这个函数(你可能是记混了),所以手动计算是最直接的方式。如果想封装成类似的函数,也可以自己定义:
weighted_sum <- function(x, w) sum(x * w) # 然后在rollapplyr里调用: tempRRI <- rollapplyr(tempVar, width=3, weighted_sum, w=tempWeights, by.column=TRUE)
这个写法和之前的代码效果完全一致。
内容的提问来源于stack exchange,提问作者Shriv
相关产品推荐
相关产品推荐

