【发布时间】:2022-01-06 07:46:52
【问题描述】:
我有一个带有值的向量 (val) 和一个指示组成员身份的向量 (group):
vec <- 1:9
group <- rep(1:3, c(2,4,3))
假设我们有K 组和总共N 值,因此两个向量的长度为N。目标是有效地构造一个稀疏的“块对角”矩阵,其中第一列保存第 1 组的值,第二列保存第 2 组的值,依此类推。但是,这些值不应“重叠”,因为每行应该只有一个值,请参见下面的解决方案。我需要在 K 和 N 非常大的情况下这样做数千次。因此,以下基于循环的解决方案不够高效:
K <- length(unique(group))
N <- length(group)
M <- matrix(0, N, K)
for(k in 1:K){
M[group == k, k] <- vec[group == k]
}
Matrix::Matrix(M, sparse = T)
9 x 3 sparse Matrix of class "dgCMatrix"
[1,] 1 . .
[2,] 2 . .
[3,] . 3 .
[4,] . 4 .
[5,] . 5 .
[6,] . 6 .
[7,] . . 7
[8,] . . 8
[9,] . . 9
出于内存原因,最好直接构造一个稀疏矩阵,而不需要基于密集N 乘以K 矩阵的中间步骤。
编辑
对于上面给出的小例子,事实证明基于循环的解决方案非常有效:
Unit: microseconds
expr min lq mean median uq max neval cld
ben 734.280 771.7000 826.8372 787.5230 805.2710 3185.158 100 b
CJR 711.187 745.1855 813.9948 766.9960 781.7495 4832.476 100 b
original 199.714 221.9520 235.4320 227.9395 236.7065 379.757 100 a
但是,当转向高维示例(N = 10,000 和 K = 1,000)时,CJR 的解决方案是速度方面的赢家:
Unit: milliseconds
expr min lq mean median uq max neval cld
ben 128.529311 133.308972 140.032070 135.921289 139.272589 289.668852 100 b
CJR 1.841474 2.055513 2.261732 2.201557 2.395925 6.330544 100 a
original 93.387806 118.348398 171.380301 125.884493 244.421699 365.871433 100 c
【问题讨论】:
-
Matrix::.bdiag()如此糟糕真的很有趣,但我想这就是文档中的注释警告的内容。大概在 very 大尺寸下,它避免分配密集矩阵的事实至少会使其比原始矩阵更好......
标签: r matrix sparse-matrix