R中非常大的稀疏矩阵的列重新缩放

Posted

技术标签:

【中文标题】R中非常大的稀疏矩阵的列重新缩放【英文标题】:Column rescaling for a very large sparse matrix in R 【发布时间】:2017-01-10 02:52:35 【问题描述】:

我在 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,以及计算和存储稀疏矩阵的转置,但是在尝试执行"/" 时问题似乎出现了。看起来稀疏矩阵在这里转换为全密集矩阵。

任何帮助将不胜感激。谢谢!

【问题讨论】:

sweep(sm, 2, colSums(sm), `/`) 呢? 与已删除建议相同的错误:> sm = sweep(sm, 2, colSums(sm), /) 错误:无法分配大小为 1442.2 Gb 的向量 【参考方案1】:

这是我们可以做的,假设AdgCMatrix

A@x <- A@x / rep.int(colSums(A), diff(A@p))

这需要对dgCMatrix类有所了解。

    @x 将非零矩阵值存储在压缩的一维数组中; @p 按列存储非零元素的累积数量,因此diff(A@p) 给出每列的非零元素数量。

我们通过该列中非零元素的数量重复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 类,没有@p@j,为非零矩阵元素提供列索引(基于0)。

【讨论】:

如果您转换为dgTMatrix - A &lt;- as(A,"dgTMatrix"),您可以使用A@x / colSums(A)[A@j+1],因为它有一个用于列索引的A@j 插槽。不错的答案 - 我学到了关于稀疏矩阵的一两件事:-) 通常我使用B = A %*% Diagonal(x = 1 / colSums(A))。但似乎您的解决方案 (A@x &lt;- A@x / rep.int(colSums(A), diff(A@p))) 有点快 (~2x-3x)。 +1

以上是关于R中非常大的稀疏矩阵的列重新缩放的主要内容,如果未能解决你的问题,请参考以下文章

R中非常大的矩阵计算有效

稀疏矩阵压缩

稀疏数组

以对数方式缩放(应用函数?)稀疏矩阵

奇异分解(SVD) 案例--用户与商家稀疏矩阵

稀疏矩阵压缩存储:CSR/CSC (Compress Sparse Row/Column)