簡體   English   中英

如何將稀疏矩陣一分為二

[英]How to split a sparse matrix into two

我有一個大的稀疏矩陣,我需要將其關聯起來,這對我來說是不可能的,因為:

  1. 由於 R 的 memory 限制,我無法將稀疏矩陣轉換為密集矩陣
  2. 我嘗試使用包bigstatsbigmemory ,我的 R 凍結了(使用 windows 10、8GB 筆記本電腦)
  3. R的Matrix package中沒有相關性function

注意:我正在嘗試以'M'X + X'M - M'M'格式關聯一個稀疏矩陣,這是不可能的,這就是為什么我試圖將稀疏矩陣分成兩個或三個,轉向密集使用as.matrix()的矩陣,然后使用cor()進行關聯,然后使用cbind() () 將相關結果合並為一個

現在:

我想問是否可以將稀疏矩陣拆分為兩個或三個部分,轉換為密集矩陣,然后關聯每個密集矩陣,然后將兩個或三個密集矩陣合並為一個,然后導出到文本文件。

我可以使用什么 function 將稀疏矩陣拆分為兩個或三個,記住稀疏矩陣的ip部分大小相等且dim相同

Formal class 'dgCMatrix' [package "Matrix"] with 7 slots
  ..@ i       : int [1:73075722]  ...
  ..@ p       : int [1:73075722] 0 0 1 1 1 1 1 2 2 2 ...
  ..@ Dim     : int [1:2] 500232 500232
  ..@ Dimnames:List of 2
  .. ..$ : NULL
  .. ..$ : NULL
  ..@ x       : num [1:73075722]  ...
  ..@ uplo    : chr "L"
  ..@ factors : list()

相關性 output 將采用以下格式:

         [,1]       [,2]       [,3]        [,4]
[1,]  1.00000000 -0.8343860  0.3612926  0.09678096
[2,] -0.83438600  1.0000000 -0.8154071  0.24611830
[3,]  0.36129256 -0.8154071  1.0000000 -0.51801346
[4,]  0.09678096  0.2461183 -0.5180135  1.00000000
[5,]  0.67411584 -0.3560782 -0.1056124  0.60987601
[6,]  0.23071712 -0.4457467  0.5117711  0.21848068
[7,]  0.49200080 -0.4246502  0.2016633  0.46971736
           [,5]       [,6]       [,7]
[1,]  0.6741158  0.2307171  0.4920008
[2,] -0.3560782 -0.4457467 -0.4246502
[3,] -0.1056124  0.5117711  0.2016633
[4,]  0.6098760  0.2184807  0.4697174
[5,]  1.0000000  0.2007979  0.7198228
[6,]  0.2007979  1.0000000  0.6965899
[7,]  0.7198228  0.6965899  1.0000000

cor() function 是一種有效計算所有列之間的pearson相關性的方法。 cor非常有效,但如果我們不介意效率下降,我們可以手動計算pearson相關性:

n_row <- nrow(res)
cor_mat <- Matrix(0L,n_row, ncol(res))
cMeans <- Matrix::colMeans(res)

for (i in seq_len(nrow(res)-1)){
  x_delta = res[, i] - cMeans[i]
  sum_x_delta_sq = sum(x_delta^2)

  for (j in (i+1):nrow(res)){
    y_delta = res[, j] - cMeans[j]

    tmp <- sum(x_delta * y_delta) / sqrt((sum_x_delta_sq * sum(y_delta^2)))
    if (abs(tmp) > 0.05) cor_mat[i, j] <- tmp
  }
}

隨着矩陣稀疏度的增加,我們可以通過分離涉及非稀疏元素的操作和涉及稀疏元素的操作來使上述更復雜但性能更高:

n_row <- nrow(res)

cor_mat <- Matrix(0L,n_row, ncol(res))
cMeans <- Matrix::colMeans(res)

for (i in 1){

  sp_i <- res[, i, drop = F]
  i_s <- sp_i@i + 1

  i_zero_delta = 0 - cMeans[i]
  i_non_zero_delta = sp_i@x - cMeans[i]

  sum_x_delta_sq = sum(c((n_row - length(i_s)) * i_zero_delta^2, i_non_zero_delta^2))

  for (j in (i+1):nrow(res)){

    sp_j <- res[, j, drop = F]
    j_s <- sp_j@i + 1

    j_zero_delta = 0L - cMeans[j]
    j_non_zero_delta = sp_j@x - cMeans[j]

    sum_y_delta_sq = sum(c((n_row - length(j_s)) * j_zero_delta^2, j_non_zero_delta^2))

    common <- intersect(i_s, j_s)
    only_i <- setdiff(i_s, j_s)
    only_j <- setdiff(j_s, i_s)
    none <- n_row - length(c(common, only_i, only_j))

    numerator = 0

    if (length(common) > 0) numerator = numerator + sum(i_non_zero_delta[match(common, i_s)] * j_non_zero_delta[match(common, j_s)])
    if (length(only_i) > 0) numerator = numerator + j_zero_delta * sum(i_non_zero_delta[match(only_i, i_s)])
    if (length(only_j) > 0) numerator = numerator + i_zero_delta * sum(j_non_zero_delta[match(only_j, j_s)])
    if (length(none) > 0)   numerator = numerator + i_zero_delta * j_zero_delta * none

    tmp <- numerator / sqrt(sum_x_delta_sq * sum_y_delta_sq)
    if (abs(tmp) > 0.05) cor_mat[i, j] <- tmp
  }
}

我通過行索引實現 sparse_matrix 的切片:

as.DF_spM <- function(data.use,chun_size="20000000",dg_class="dgCMatrix") {
    lapply(  split(seq(nrow(data.use)), (seq(nrow(data.use))-1) %/% as.numeric(chun_size) )  , function(nx) {
        switch(dg_class,
               dgTMatrix = {as(as.matrix(data.use[nx,]),"dgTMatrix")},
               dgCMatrix = {as(as.matrix(data.use[nx,]),"dgCMatrix")},
               dgRMatrix = {as(as.matrix(data.use[nx,]),"dgRMatrix")}
               )
        }) %>% Matrix.utils::rBind.fill()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM