在 R 中跨变量使用 ccf() 和 rollapply
Using ccf() with rollapply across variables in R
我有 3 列数据,每列 10 行,如下所示
set.seed(101)
inputx <- rnorm(1000,mean = 3,sd=2)
inputy <- rnorm(1000,mean = 2,sd=1)
inputz <- rnorm(1000,mean = 1,sd=3)
example <- cbind(inputx,inputy,inputz)
> head(example,10)
inputx inputy inputz
[1,] 2.347927 2.50319581 4.4931430
[2,] 4.104924 -0.09747067 -0.2836938
[3,] 1.650112 1.90551542 0.9146087
[4,] 3.428719 3.01454241 4.9332929
[5,] 3.621538 1.92059955 2.4220865
[6,] 5.347933 1.74487106 2.9122764
[7,] 4.237580 2.78095054 7.8622898
[8,] 2.774531 3.20741266 -1.5977934
[9,] 4.834057 1.09214734 -0.5482315
[10,] 2.553481 0.59679215 0.5285020
我的实际数据总共有 10 个变量,但为了简单起见,我只使用了 3 个。
对于下面的每个排列,我想使用大小为 4
的滚动 window 来计算 ccf
inputx,inputx
inputx,inputy
inputx,inputz
inputy,inputx
inputy,inputy
inputy,inputz
inputz,inputx
inputz,inputy
inputz,inputz
例如
ccf(example[1:4,1],example[1:4,2])
ccf(example[2:5,1],example[2:5,2])
.
.
.
ccf(example[7:10,1],example[7:10,2])
如您所见,上面的示例仅适用于第 1 列和第 2 列,但我希望使用滚动 window 方法对所有列执行此操作。
使用 rollapply 函数可以轻松处理滚动 window 过程,您可以在其中指定 window 的大小,并将 by.column 指定为 FALSE,这样它就不会应用分别作用于每一列。
如果我想对每一列滚动应用诸如均值之类的函数,我可以这样做,但是所有组合的跨列循环让我大吃一惊,我无法弄清楚。
test <- rollapply(example[,c(1,2)],4,mean, by.column=TRUE)
对于输出,ccf 结果应按行存储,尺寸应为 10x9,因为原始数据中有 10 行,ccf 函数有 9 个排列。输出的前 3 行将为 NA,因为滚动 window 使用大小 4。下面的值仅用于说明目的,并不是真正的输出值。
输出 ->
xx xy xz yx yy yz zx zy zz
[1,] NA NA NA NA NA NA NA NA NA
[2,] NA NA NA NA NA NA NA NA NA
[3,] NA NA NA NA NA NA NA NA NA
[4,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[5,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[6,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[7,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[8,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[9,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[10,].1 .2 .3 .2 .8 .5 .3 .5 .9
如果能在所有排列中应用循环,我将不胜感激,我想如果我得到了它,我就可以做 rollapply 包装器来实现滑动 window。
使用expand.grid
生成组合列表。然后你可以这样做:
combos <- expand.grid(colnames(example), colnames(example), stringsAsFactors=F)
sapply(1:nrow(combos), function(j) {
MY_CALCULATION
})
我真的不知道你想要达到什么目的。我没有在 base R 中看到函数 rollapply
但我知道你可以使用 combn
函数:
我将为您提供上述示例的所有 4 window 组合,但仅适用于 10 个数字。我无法生成 1000 个数字,但您可以更改代码来执行此操作。
set.seed(101)
inputx <- rnorm(10,mean = 3,sd=2)
inputy <- rnorm(10,mean = 2,sd=1)
inputz <- rnorm(10,mean = 1,sd=3)
example <- cbind(inputx,inputy,inputz)# Has only 10 rows. just for illustration
a=lapply(1:(nrow(example)-3),function(x) x:(x+3))# all the four window combinations
Map(combn,ncol(example),2,c(function(x,y) example[y,x]),y=a)
上面的代码为您提供了按您想要的方式分解的全部数据。然后您可以随意操作它。如果这有帮助,请告诉我们。谢谢
1) ccf(x, y)
两个 4 向量 x
和 y
给出一个 7 向量所以输出将有 3 * 3 * 7 = 63 列,而不是问题中所述的 9 列。
在评论中发帖人说另一个函数可以代替 ccf
所以下面我们假设 cov(x, y)
因为它输出一个标量而不是一个 7 向量所以会给出 10 x 9 输出。在这种特殊情况下,cov(cbind(x, y, z))
产生一个 3x3 矩阵,当展平时给出一个 9 向量。
rollapplyr(head(example, 10), 4, function(x) c(cov(x)), fill = NA, by.column = FALSE)
给出以下 10x9 矩阵:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] NA NA NA NA NA NA NA NA NA
[2,] NA NA NA NA NA NA NA NA NA
[3,] NA NA NA NA NA NA NA NA NA
[4,] 1.1990739 -0.72070179 -0.3951435 -0.72070179 1.8590569 3.1565993 -0.3951435 3.1565993 6.718376
[5,] 1.1503463 -0.51712419 0.1548365 -0.51712419 1.6830055 2.6102211 0.1548365 2.6102211 5.058550
[6,] 2.2854029 -0.12857123 1.1658204 -0.12857123 0.3413027 0.7821381 1.1658204 0.7821381 2.753662
[7,] 0.7473036 -0.31336885 -0.2743693 -0.31336885 0.3923239 1.1959920 -0.2743693 1.1959920 6.109035
[8,] 1.1727627 -0.53344663 2.2960862 -0.53344663 0.4851109 -0.5067012 2.2960862 -0.5067012 15.027672
[9,] 1.2381071 -0.88053417 1.5728089 -0.88053417 0.9289009 0.7283704 1.5728089 0.7283704 18.179175
[10,] 1.2353345 -0.05021654 1.7008923 -0.05021654 1.6116281 1.4902571 1.7008923 1.4902571 18.399713
2) 或给出相同结果的这个:
k <- ncol(example)
g <- expand.grid(1:k, 1:k)
Cov <- function(x) apply(g, 1, function(ix) cov(x[, ix[1]], x[, ix[2]]))
rollapplyr(head(example, 10), 4, Cov, by.column = FALSE, fill = NA)
请注意,在 cov
的情况下,它会生成一个对称矩阵(3 个下三角值等于 3 个上三角值),因此我们可能只希望输出对角线和上三角部分,如果在这种情况下,我们可以使用 upper.tri
对其进行子集化。
我有 3 列数据,每列 10 行,如下所示
set.seed(101)
inputx <- rnorm(1000,mean = 3,sd=2)
inputy <- rnorm(1000,mean = 2,sd=1)
inputz <- rnorm(1000,mean = 1,sd=3)
example <- cbind(inputx,inputy,inputz)
> head(example,10)
inputx inputy inputz
[1,] 2.347927 2.50319581 4.4931430
[2,] 4.104924 -0.09747067 -0.2836938
[3,] 1.650112 1.90551542 0.9146087
[4,] 3.428719 3.01454241 4.9332929
[5,] 3.621538 1.92059955 2.4220865
[6,] 5.347933 1.74487106 2.9122764
[7,] 4.237580 2.78095054 7.8622898
[8,] 2.774531 3.20741266 -1.5977934
[9,] 4.834057 1.09214734 -0.5482315
[10,] 2.553481 0.59679215 0.5285020
我的实际数据总共有 10 个变量,但为了简单起见,我只使用了 3 个。
对于下面的每个排列,我想使用大小为 4
的滚动 window 来计算 ccf inputx,inputx
inputx,inputy
inputx,inputz
inputy,inputx
inputy,inputy
inputy,inputz
inputz,inputx
inputz,inputy
inputz,inputz
例如
ccf(example[1:4,1],example[1:4,2])
ccf(example[2:5,1],example[2:5,2])
.
.
.
ccf(example[7:10,1],example[7:10,2])
如您所见,上面的示例仅适用于第 1 列和第 2 列,但我希望使用滚动 window 方法对所有列执行此操作。
使用 rollapply 函数可以轻松处理滚动 window 过程,您可以在其中指定 window 的大小,并将 by.column 指定为 FALSE,这样它就不会应用分别作用于每一列。
如果我想对每一列滚动应用诸如均值之类的函数,我可以这样做,但是所有组合的跨列循环让我大吃一惊,我无法弄清楚。
test <- rollapply(example[,c(1,2)],4,mean, by.column=TRUE)
对于输出,ccf 结果应按行存储,尺寸应为 10x9,因为原始数据中有 10 行,ccf 函数有 9 个排列。输出的前 3 行将为 NA,因为滚动 window 使用大小 4。下面的值仅用于说明目的,并不是真正的输出值。
输出 ->
xx xy xz yx yy yz zx zy zz
[1,] NA NA NA NA NA NA NA NA NA
[2,] NA NA NA NA NA NA NA NA NA
[3,] NA NA NA NA NA NA NA NA NA
[4,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[5,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[6,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[7,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[8,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[9,] .1 .2 .3 .2 .8 .5 .3 .5 .9
[10,].1 .2 .3 .2 .8 .5 .3 .5 .9
如果能在所有排列中应用循环,我将不胜感激,我想如果我得到了它,我就可以做 rollapply 包装器来实现滑动 window。
使用expand.grid
生成组合列表。然后你可以这样做:
combos <- expand.grid(colnames(example), colnames(example), stringsAsFactors=F)
sapply(1:nrow(combos), function(j) {
MY_CALCULATION
})
我真的不知道你想要达到什么目的。我没有在 base R 中看到函数 rollapply
但我知道你可以使用 combn
函数:
我将为您提供上述示例的所有 4 window 组合,但仅适用于 10 个数字。我无法生成 1000 个数字,但您可以更改代码来执行此操作。
set.seed(101)
inputx <- rnorm(10,mean = 3,sd=2)
inputy <- rnorm(10,mean = 2,sd=1)
inputz <- rnorm(10,mean = 1,sd=3)
example <- cbind(inputx,inputy,inputz)# Has only 10 rows. just for illustration
a=lapply(1:(nrow(example)-3),function(x) x:(x+3))# all the four window combinations
Map(combn,ncol(example),2,c(function(x,y) example[y,x]),y=a)
上面的代码为您提供了按您想要的方式分解的全部数据。然后您可以随意操作它。如果这有帮助,请告诉我们。谢谢
1) ccf(x, y)
两个 4 向量 x
和 y
给出一个 7 向量所以输出将有 3 * 3 * 7 = 63 列,而不是问题中所述的 9 列。
在评论中发帖人说另一个函数可以代替 ccf
所以下面我们假设 cov(x, y)
因为它输出一个标量而不是一个 7 向量所以会给出 10 x 9 输出。在这种特殊情况下,cov(cbind(x, y, z))
产生一个 3x3 矩阵,当展平时给出一个 9 向量。
rollapplyr(head(example, 10), 4, function(x) c(cov(x)), fill = NA, by.column = FALSE)
给出以下 10x9 矩阵:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] NA NA NA NA NA NA NA NA NA
[2,] NA NA NA NA NA NA NA NA NA
[3,] NA NA NA NA NA NA NA NA NA
[4,] 1.1990739 -0.72070179 -0.3951435 -0.72070179 1.8590569 3.1565993 -0.3951435 3.1565993 6.718376
[5,] 1.1503463 -0.51712419 0.1548365 -0.51712419 1.6830055 2.6102211 0.1548365 2.6102211 5.058550
[6,] 2.2854029 -0.12857123 1.1658204 -0.12857123 0.3413027 0.7821381 1.1658204 0.7821381 2.753662
[7,] 0.7473036 -0.31336885 -0.2743693 -0.31336885 0.3923239 1.1959920 -0.2743693 1.1959920 6.109035
[8,] 1.1727627 -0.53344663 2.2960862 -0.53344663 0.4851109 -0.5067012 2.2960862 -0.5067012 15.027672
[9,] 1.2381071 -0.88053417 1.5728089 -0.88053417 0.9289009 0.7283704 1.5728089 0.7283704 18.179175
[10,] 1.2353345 -0.05021654 1.7008923 -0.05021654 1.6116281 1.4902571 1.7008923 1.4902571 18.399713
2) 或给出相同结果的这个:
k <- ncol(example)
g <- expand.grid(1:k, 1:k)
Cov <- function(x) apply(g, 1, function(ix) cov(x[, ix[1]], x[, ix[2]]))
rollapplyr(head(example, 10), 4, Cov, by.column = FALSE, fill = NA)
请注意,在 cov
的情况下,它会生成一个对称矩阵(3 个下三角值等于 3 个上三角值),因此我们可能只希望输出对角线和上三角部分,如果在这种情况下,我们可以使用 upper.tri
对其进行子集化。