我想使用滚动窗口生成协方差矩阵(和平均向量)。但是在我的所有尝试rollapply
中,cov
堆叠了协方差矩阵并且用完了预先分配的空间(例如,如果我的原始数据有40个观察值,则rollapply
无法返回更多超过40行)。
有没有办法让rollapply
返回一个矩阵列表?或者返回大于原始data.frame
的{{1}},我可以手动将其分成列表?我的最终目标是采用一个面板,将面板分成一个单独的data.frame
列表,计算每个数据框的滚动协方差和均值,然后使用这些协方差列表和下游方法来比较一堆个体
这是一些代码。我的问题是data.frame
不会返回所有协方差矩阵计算的数据。是我编写自己的my.fun
代码的最佳选择吗?或者我自己的rollapply
返回一个我转换回矩阵的向量?谢谢!
cov
答案 0 :(得分:2)
在看了rollapply.zoo
代码之后,我认为没有办法让它做你想做的事。滚动你自己的功能并不困难(双关语)。
rollcov <- function(x, width=10) {
len <- NROW(x)
add <- rep(1:(len-width)-1,each=width)
seq.list <- split(rep(1:width,len-width)+add, add)
lapply(seq.list, function(y) cov(x[y,]))
}
rollcov(data.list[[1]][,c("one","two","three")],10)
all <- lapply(data.list, function(x) rollcov(x[,c("one","two","three")],10))
答案 1 :(得分:2)
我意识到我可以欺骗rollapply返回一个向量,然后将该向量弯曲回矩阵。诀窍是使用alply
包中的plyr
将向量弯曲回矩阵。
library("plyr")
library("zoo")
data.df <- data.frame(sic = rep(1:10, each = 40),
year = rep(1:40, len = 10*40),
one = rnorm(10*40),
two = 2*rnorm(10*40),
three = 3*rnorm(10*40))
data.list <- split(data.df, data$sic)
data.list <- lapply(data.list, zoo)
my.fun <- function(x) {
x <- x[, c("one", "two", "three")]
rollapply(x,
width = 10,
function(x) as.vector(cov(x)),
by.column = F,
align = "right")
}
my.fun.2 <- function(x) {
alply(x, 1, matrix, nrow = sqrt(ncol(x)))
}
cov.list <- lapply(data.list, FUN = my.fun)
cov.list.2 <- lapply(cov.list, my.fun.2)
或者,对于数组列表,我可以将alply
替换为aaply
。
答案 2 :(得分:2)
删除第二个data.list<-
并修改my.fun
,以便给定data.df
我们有以下内容(与原始内容相当接近):
data.list <- split(data.df, data.df$sic)
my.fun <- function(x) {
z <- zoo(x[, c("one", "two", "three")], x$year)
ccov <- function(x) c(cov(x))
r <- rollapplyr(z, width = 10, FUN = ccov, by.column = FALSE)
toMat <- function(tt) matrix(r[tt], ncol(z))
sapply(paste(time(r)), toMat, simplify = FALSE) # sapply(char,...) adds names
}
cov.list <- lapply(data.list, FUN = my.fun)
编辑:轻微简化。