R中非常大的稀疏矩阵的列重新缩放
Column rescaling for a very large sparse matrix in R
我在 R 中有一个非常大的 (~500,000 x ~500,000) 稀疏矩阵,我试图将每一列除以其总和:
sm = t(t(sm) / colSums(sm))
但是,当我这样做时,出现以下错误:
# Error in evaluating the argument 'x' in selecting a method for function 't':
# Error: cannot allocate vector of size 721.1 Gb
在 R 中有更好的方法吗?我可以很好地存储 colSums
,也可以计算和存储稀疏矩阵的转置,但是在尝试执行 "/"
时问题似乎来了。看起来稀疏矩阵在这里被转换为全密集矩阵。
如有任何帮助,我们将不胜感激。谢谢!
这就是我们可以做的,假设 A
是 dgCMatrix
:
A@x <- A@x / rep.int(colSums(A), diff(A@p))
这需要对dgCMatrix
class有所了解。
@x
在打包的一维数组中存储 none-零矩阵值;
@p
按列存储非零元素的累积数量,因此 diff(A@p)
给出每列非零元素的数量。
我们按该列中 none-零元素的数量重复 colSums(A)
的每个元素,然后将 A@x
除以该向量。最后,我们通过重新缩放的值更新 A@x
。通过这种方式,列重新缩放以稀疏方式完成。
示例:
library(Matrix)
set.seed(2); A <- Matrix(rbinom(100,10,0.05), nrow = 10)
#10 x 10 sparse Matrix of class "dgCMatrix"
# [1,] . . 1 . 2 . 1 . . 2
# [2,] 1 . . . . . 1 . 1 .
# [3,] . 1 1 1 . 1 1 . . .
# [4,] . . . 1 . 2 . . . .
# [5,] 2 . . . 2 . 1 . . .
# [6,] 2 1 . 1 1 1 . 1 1 .
# [7,] . 2 . 1 2 1 . . 2 .
# [8,] 1 . . . . 3 . 1 . .
# [9,] . . 2 1 . 1 . . 1 .
#[10,] . . . . 1 1 . . . .
diff(A@p) ## number of non-zeros per column
# [1] 4 3 3 5 5 7 4 2 4 1
colSums(A) ## column sums
# [1] 6 4 4 5 8 10 4 2 5 2
A@x <- A@x / rep.int(colSums(A), diff(A@p)) ## sparse column rescaling
#10 x 10 sparse Matrix of class "dgCMatrix"
# [1,] . . 0.25 . 0.250 . 0.25 . . 1
# [2,] 0.1666667 . . . . . 0.25 . 0.2 .
# [3,] . 0.25 0.25 0.2 . 0.1 0.25 . . .
# [4,] . . . 0.2 . 0.2 . . . .
# [5,] 0.3333333 . . . 0.250 . 0.25 . . .
# [6,] 0.3333333 0.25 . 0.2 0.125 0.1 . 0.5 0.2 .
# [7,] . 0.50 . 0.2 0.250 0.1 . . 0.4 .
# [8,] 0.1666667 . . . . 0.3 . 0.5 . .
# [9,] . . 0.50 0.2 . 0.1 . . 0.2 .
#[10,] . . . . 0.125 0.1 . . . .
@thelatemail提到了另一种方法,首先将dgCMatrix
转换为dgTMatrix
:
AA <- as(A, "dgTMatrix")
A@x <- A@x / colSumns(A)[AA@j + 1L]
对于 dgTMatrix
class 没有 @p
但 @j
,给出 none 零矩阵元素的列索引(基于 0)。
我在 R 中有一个非常大的 (~500,000 x ~500,000) 稀疏矩阵,我试图将每一列除以其总和:
sm = t(t(sm) / colSums(sm))
但是,当我这样做时,出现以下错误:
# Error in evaluating the argument 'x' in selecting a method for function 't':
# Error: cannot allocate vector of size 721.1 Gb
在 R 中有更好的方法吗?我可以很好地存储 colSums
,也可以计算和存储稀疏矩阵的转置,但是在尝试执行 "/"
时问题似乎来了。看起来稀疏矩阵在这里被转换为全密集矩阵。
如有任何帮助,我们将不胜感激。谢谢!
这就是我们可以做的,假设 A
是 dgCMatrix
:
A@x <- A@x / rep.int(colSums(A), diff(A@p))
这需要对dgCMatrix
class有所了解。
@x
在打包的一维数组中存储 none-零矩阵值;@p
按列存储非零元素的累积数量,因此diff(A@p)
给出每列非零元素的数量。
我们按该列中 none-零元素的数量重复 colSums(A)
的每个元素,然后将 A@x
除以该向量。最后,我们通过重新缩放的值更新 A@x
。通过这种方式,列重新缩放以稀疏方式完成。
示例:
library(Matrix)
set.seed(2); A <- Matrix(rbinom(100,10,0.05), nrow = 10)
#10 x 10 sparse Matrix of class "dgCMatrix"
# [1,] . . 1 . 2 . 1 . . 2
# [2,] 1 . . . . . 1 . 1 .
# [3,] . 1 1 1 . 1 1 . . .
# [4,] . . . 1 . 2 . . . .
# [5,] 2 . . . 2 . 1 . . .
# [6,] 2 1 . 1 1 1 . 1 1 .
# [7,] . 2 . 1 2 1 . . 2 .
# [8,] 1 . . . . 3 . 1 . .
# [9,] . . 2 1 . 1 . . 1 .
#[10,] . . . . 1 1 . . . .
diff(A@p) ## number of non-zeros per column
# [1] 4 3 3 5 5 7 4 2 4 1
colSums(A) ## column sums
# [1] 6 4 4 5 8 10 4 2 5 2
A@x <- A@x / rep.int(colSums(A), diff(A@p)) ## sparse column rescaling
#10 x 10 sparse Matrix of class "dgCMatrix"
# [1,] . . 0.25 . 0.250 . 0.25 . . 1
# [2,] 0.1666667 . . . . . 0.25 . 0.2 .
# [3,] . 0.25 0.25 0.2 . 0.1 0.25 . . .
# [4,] . . . 0.2 . 0.2 . . . .
# [5,] 0.3333333 . . . 0.250 . 0.25 . . .
# [6,] 0.3333333 0.25 . 0.2 0.125 0.1 . 0.5 0.2 .
# [7,] . 0.50 . 0.2 0.250 0.1 . . 0.4 .
# [8,] 0.1666667 . . . . 0.3 . 0.5 . .
# [9,] . . 0.50 0.2 . 0.1 . . 0.2 .
#[10,] . . . . 0.125 0.1 . . . .
@thelatemail提到了另一种方法,首先将dgCMatrix
转换为dgTMatrix
:
AA <- as(A, "dgTMatrix")
A@x <- A@x / colSumns(A)[AA@j + 1L]
对于 dgTMatrix
class 没有 @p
但 @j
,给出 none 零矩阵元素的列索引(基于 0)。