在大型稀疏矩阵上滚动应用
Rollapply on large sparse matrices
有没有一种方法可以执行 rollapply/rollsum 计算固定长度 windows 上 稀疏 矩阵的行总和?为了方便起见,我正在使用 dgTMatrix
,但我的问题并不特定于此 class。例如,考虑生成一个 8 x 10
稀疏矩阵。
library(Matrix)
i <- c(1,3:8); j <- c(2,9,6:10); x <- 7 * (1:7)
A <- sparseMatrix(i, j, x = x, giveCsparse = FALSE)
> A
8 x 10 sparse Matrix of class "dgTMatrix"
[1,] . 7 . . . . . . . .
[2,] . . . . . . . . . .
[3,] . . . . . . . . 14 .
[4,] . . . . . 21 . . . .
[5,] . . . . . . 28 . . .
[6,] . . . . . . . 35 . .
[7,] . . . . . . . . 42 .
[8,] . . . . . . . . . 49
在不首先强制转换为矩阵的情况下(例如 as.matrix()),一种天真的方法是使用 sapply
计算每个 window=2
列的行总和,从而得到 8 x 5
密集矩阵.
window = 2
starts = seq(1,dim(A)[2],by=window)
A_rollsum <- sapply(starts, function(x) Matrix::rowSums(A[, x:(x+window-1)]))
> A_rollsum
[,1] [,2] [,3] [,4] [,5]
[1,] 7 0 0 0 0
[2,] 0 0 0 0 0
[3,] 0 0 0 0 14
[4,] 0 0 21 0 0
[5,] 0 0 0 28 0
[6,] 0 0 0 35 0
[7,] 0 0 0 0 42
[8,] 0 0 0 0 49
这对于大型稀疏矩阵来说效率不高。
1) rollapply
逐列工作,显然你想逐行转置它,如图所示使用 rollapply 并转回:
t(rollapply(t(as.matrix(A)), 2, by = 2, sum))
给予:
[,1] [,2] [,3] [,4] [,5]
[1,] 7 0 0 0 0
[2,] 0 0 0 0 0
[3,] 0 0 0 0 14
[4,] 0 0 21 0 0
[5,] 0 0 0 28 0
[6,] 0 0 0 35 0
[7,] 0 0 0 0 42
[8,] 0 0 0 0 49
2) 上面使用了稠密矩阵,但如果你真的需要稀疏矩阵,请注意这里的 rollapply 是一个线性运算符,所以我们可以计算它的矩阵,然后使用稀疏矩阵乘法。
d <- rollapply(diag(10), 2, by = 2, sum)
A %*% t(d)
旧
问题已更改。这是原始问题的答案。
尝试r1
。我们证明它等于 r2
.
r1 <- rollapply(rowSums(A), 3, c)
r2 <- rollapply(as.matrix(A), 3, rowSums, by.column = FALSE)
identical(r1, r2)
## [1] TRUE
r1
因此 r2
等于:
> r1
[,1] [,2] [,3]
[1,] 7 0 14
[2,] 0 14 21
[3,] 14 21 28
[4,] 21 28 35
[5,] 28 35 42
[6,] 35 42 49
有没有一种方法可以执行 rollapply/rollsum 计算固定长度 windows 上 稀疏 矩阵的行总和?为了方便起见,我正在使用 dgTMatrix
,但我的问题并不特定于此 class。例如,考虑生成一个 8 x 10
稀疏矩阵。
library(Matrix)
i <- c(1,3:8); j <- c(2,9,6:10); x <- 7 * (1:7)
A <- sparseMatrix(i, j, x = x, giveCsparse = FALSE)
> A
8 x 10 sparse Matrix of class "dgTMatrix"
[1,] . 7 . . . . . . . .
[2,] . . . . . . . . . .
[3,] . . . . . . . . 14 .
[4,] . . . . . 21 . . . .
[5,] . . . . . . 28 . . .
[6,] . . . . . . . 35 . .
[7,] . . . . . . . . 42 .
[8,] . . . . . . . . . 49
在不首先强制转换为矩阵的情况下(例如 as.matrix()),一种天真的方法是使用 sapply
计算每个 window=2
列的行总和,从而得到 8 x 5
密集矩阵.
window = 2
starts = seq(1,dim(A)[2],by=window)
A_rollsum <- sapply(starts, function(x) Matrix::rowSums(A[, x:(x+window-1)]))
> A_rollsum
[,1] [,2] [,3] [,4] [,5]
[1,] 7 0 0 0 0
[2,] 0 0 0 0 0
[3,] 0 0 0 0 14
[4,] 0 0 21 0 0
[5,] 0 0 0 28 0
[6,] 0 0 0 35 0
[7,] 0 0 0 0 42
[8,] 0 0 0 0 49
这对于大型稀疏矩阵来说效率不高。
1) rollapply
逐列工作,显然你想逐行转置它,如图所示使用 rollapply 并转回:
t(rollapply(t(as.matrix(A)), 2, by = 2, sum))
给予:
[,1] [,2] [,3] [,4] [,5]
[1,] 7 0 0 0 0
[2,] 0 0 0 0 0
[3,] 0 0 0 0 14
[4,] 0 0 21 0 0
[5,] 0 0 0 28 0
[6,] 0 0 0 35 0
[7,] 0 0 0 0 42
[8,] 0 0 0 0 49
2) 上面使用了稠密矩阵,但如果你真的需要稀疏矩阵,请注意这里的 rollapply 是一个线性运算符,所以我们可以计算它的矩阵,然后使用稀疏矩阵乘法。
d <- rollapply(diag(10), 2, by = 2, sum)
A %*% t(d)
旧
问题已更改。这是原始问题的答案。
尝试r1
。我们证明它等于 r2
.
r1 <- rollapply(rowSums(A), 3, c)
r2 <- rollapply(as.matrix(A), 3, rowSums, by.column = FALSE)
identical(r1, r2)
## [1] TRUE
r1
因此 r2
等于:
> r1
[,1] [,2] [,3]
[1,] 7 0 14
[2,] 0 14 21
[3,] 14 21 28
[4,] 21 28 35
[5,] 28 35 42
[6,] 35 42 49