使用zoo包rollapply获多列结果而非单列的问题排查与解决
R语言rollapply返回矩阵而非单列向量的问题分析与解决
问题场景
使用zoo包的rollapply对向量做5元素滚动窗口计算,预期得到每个窗口对应"Yes"/"No"的单列向量,但实际返回了6行5列的矩阵。原代码如下:
library(zoo) set.seed(101) foo <- data.frame("V1" = sample(seq(-5, 5), replace = TRUE, size = 100)) result <- rollapply(foo$V1, width = 5, FUN = function(x) ifelse(x < 0, "Yes", "No"), align = "right", by.column = FALSE, fill = NA) head(result)
原因分析
问题出在自定义的FUN函数上:原函数里的ifelse(x < 0, "Yes", "No")会对滚动窗口内的每一个元素单独判断,返回一个长度为5的向量。rollapply会把每个窗口的结果拼接起来,最终形成行数为窗口数、列数为窗口宽度的矩阵,这和预期的单列结果不符。
从你提供的临时循环代码能看出,实际需求是判断每个5元素窗口中是否存在负数,返回单个"Yes"/"No"(或布尔值),而非对窗口内每个元素做判断。
修正后的代码
修改FUN函数,先判断窗口内是否存在负数,再返回对应的"Yes"/"No",确保每个窗口只返回单个值:
library(zoo) set.seed(101) foo <- data.frame("V1" = sample(seq(-5, 5), replace = TRUE, size = 100)) # 修正后的rollapply调用 result <- rollapply(foo$V1, width = 5, FUN = function(x) ifelse(any(x < 0), "Yes", "No"), align = "right", fill = NA) head(result)
此时result会是一个长度为100的单列向量,前4个值为NA(因为align="right",前4个位置无法形成完整的5元素窗口),后续每个位置对应右侧5元素窗口的判断结果。
临时循环实现(你的原始方案)
如果偏好循环方式,也可以保留你的实现,注意可以把布尔值转成"Yes"/"No"更贴合需求:
# 初始化结果列 foo$V2 <- NA # 滚动窗口循环判断 for (i in 1:(length(foo$V1) - 4)) { # 判断窗口内是否存在负数,转成Yes/No foo$V2[i + 4] <- ifelse(any(foo$V1[i:(i + 4)] < 0), "Yes", "No") } head(foo$V2)
内容的提问来源于stack exchange,提问作者Borexino
相关产品推荐
相关产品推荐

