对R中非常大的稀疏矩阵进行重新缩放

时间:2016-09-02 05:19:44

标签: r matrix normalization sparse-matrix

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

非常感谢任何帮助。谢谢!

1 个答案:

答案 0 :(得分:6)

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

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

这需要对dgCMatrix类有所了解。

  1. @x在打包的1D数组中存储非零矩阵值;
  2. @p按列存储累计非零元素数,因此diff(A@p)给出每列的非零元素数。
  3. 我们通过该列中非零元素的数量重复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)。