如何将稀疏矩阵一分为二

时间:2019-11-04 01:18:12

标签: r matrix sparse-matrix correlation

我有一个大的稀疏矩阵,我需要将它关联起来,这对我来说是不可能的,因为:

  1. 由于R的内存限制,我无法将稀疏矩阵转换为密集矩阵
  2. 我尝试使用软件包bigstatsbigmemory,但我的R冻结了(使用Windows 10、8GB笔记本电脑)
  3. R的Matrix包中没有相关函数

NB:我试图以'M'X + X'M - M'M'的格式关联稀疏矩阵,这就是为什么我试图将稀疏矩阵分成两个或三个,并使用{{1 }}然后使用as.matrix()进行关联,然后使用cor()

将相关结果合并为一个

现在:

我想问一问是否有可能将稀疏矩阵分为两部分或三部分,转换为稠密矩阵,然后关联每个稠密矩阵,然后将两个或三个稠密矩阵绑定为一个,然后导出到文本文件。

考虑到稀疏矩阵的cbind()i部分的大小相等且具有相同的p,我可以使用什么函数将稀疏矩阵分为两个或三个?

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()

1 个答案:

答案 0 :(得分:1)

cor()函数是一种有效计算所有列之间的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
  }
}