r - 如何在大型稀疏矩阵中组合具有相同名称的列

标签 r performance sparse-matrix

我有一个来自Matrix包的稀疏dgTMatrix,它拾取了一些重复的colnames 。我想通过对具有相同名称的列求和来组合这些,形成一个简化的矩阵。

我找到了this post ,我将其改编为稀疏矩阵运算。但是:对于大型对象来说它仍然非常慢。我想知道是否有人有更好的解决方案,直接对稀疏矩阵的索引元素进行操作,速度会更快。例如,A@jA@Dimnames[[2]] 中的标签进行索引(从零开始) ,可以对其进行压缩并用于重新索引 A@j 。 (注意:这就是为什么我使用三元组稀疏矩阵形式而不是列稀疏矩阵的 Matrix 默认值,因为弄清楚 p 值每次都会让我头疼。)

require(Matrix)

# set up a (triplet) sparseMatrix
A <- sparseMatrix(i = c(1, 2, 1, 2, 1, 2), j = 1:6, x = rep(1:3, 2), 
                  giveCsparse = FALSE,
                  dimnames = list(paste0("r", 1:2), rep(letters[1:3], 2)))
A
## 2 x 6 sparse Matrix of class "dgTMatrix"
##    a b c a b c
## r1 1 . 3 . 2 .
## r2 . 2 . 1 . 3

str(A)
## Formal class 'dgTMatrix' [package "Matrix"] with 6 slots
##   ..@ i       : int [1:6] 0 1 0 1 0 1
##   ..@ j       : int [1:6] 0 1 2 3 4 5
##   ..@ Dim     : int [1:2] 2 6
##   ..@ Dimnames:List of 2
##   .. ..$ : chr [1:2] "r1" "r2"
##   .. ..$ : chr [1:6] "a" "b" "c" "a" ...
##   ..@ x       : num [1:6] 1 2 3 1 2 3
##   ..@ factors : list()

# my matrix-based attempt
OP1 <- function(x) {
    nms <- colnames(x)
    if (any(duplicated(nms))) 
        x <- x %*% Matrix(sapply(unique(nms),"==", nms))
    x
} 
OP1(A)
## 2 x 3 sparse Matrix of class "dgCMatrix"
##    a b c
## r1 1 2 3
## r2 1 2 3

它工作得很好,但在我打算使用它的巨大稀疏对象上似乎相当慢。这是一个更大的项目:

# now something bigger, for testing
set.seed(10)
nr <- 10000     # rows
nc <- 26*100    # columns - 100 repetitions of a-z
nonZeroN <- round(nr * nc / 3)  # two-thirds sparse
B <- sparseMatrix(i = sample(1:nr, size = nonZeroN, replace = TRUE), 
                  j = sample(1:nc, size = nonZeroN, replace = TRUE),
                  x = round(runif(nonZeroN)*5+1),
                  giveCsparse = FALSE, 
                  dimnames =  list(paste0("r", 1:nr), rep(letters, nc/26)))
print(B[1:5, 1:10], col.names = TRUE)
## 5 x 10 sparse Matrix of class "dgTMatrix"
##     a b c  d e f g h i  j
## r1  . . 5  . . 2 . . .  .
## r2  . . .  . . . . . .  4
## r4  . . .  . . . . 3 3  .
## r3  2 2 .  3 . . . 3 .  .
## r5  3 . .  1 . . . . .  5

require(microbenchmark)
microbenchmark(OPmatrixCombine1 = OP1(B), times = 30)
## Unit: milliseconds
##             expr      min       lq     mean   median       uq      max neval
## OPmatrixCombine1 578.9222 619.3912 665.6301 631.4219 646.2716 1013.777    30

有没有更好的方法,更好意味着更快,并且如果可能的话,不需要构造额外的大型对象?

最佳答案

这是使用我想要的索引重新索引的尝试,这是我在 friend 的帮助下发现的( Patrick 是你吗?)。它重新索引 j 值,并使用 sparseMatrix() 的非常方便的功能,将索引位置为的元素的 x 值添加在一起。一样。

OP2 <- function(x) {
    nms <- colnames(x)
    uniquenms <- unique(nms)
    # build the sparseMatrix again: x's with same index values are automatically
    # added together, keeping in mind that indexes stored from 0 but built from 1
    sparseMatrix(i = x@i + 1, 
                 j = match(nms, uniquenms)[x@j + 1],
                 x = x@x,
                 dimnames = list(rownames(x), uniquenms),
                 giveCsparse = FALSE)
}

结果是相同的:

OP2(A)
## 2 x 3 sparse Matrix of class "dgCMatrix"
##    a b c
## r1 1 2 3
## r2 1 2 3

all.equal(as(OP1(B), "dgTMatrix"), OP2(B))
## [1] TRUE

但更快:

require(microbenchmark)
microbenchmark(OPmatrixCombine1 = OP1(B), 
               OPreindexSparse = OP2(B),
               times = 30)
## Unit: relative
##              expr      min       lq     mean   median       uq      max neval
##  OPmatrixCombine1 1.756769 1.307651 1.360487 1.341814 1.346864 1.460626    30
##   OPreindexSparse 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    30

关于r - 如何在大型稀疏矩阵中组合具有相同名称的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36778166/

相关文章:

python - Scipy:稀疏矩阵条件删除列

linux - 从 shell 脚本执行 R 命令

r - 字符串作为 R 中的因子

java - 使用 jpexport 时出错(导出 jprofiler .jps 文件)

python - 如何加快Python代码在功能强大的计算机上运行的速度?

python - 创建对角稀疏矩阵的有效方法

c++ - 在 Eigen 中求解稀疏上三角系统?

r - 在R中使用神经网络进行时间序列预测的示例

r - 如何使用 igraph 包在 R 中进行求和

c++ - 什么时候应该在 RapidJSON 中使用 CrtAllocator 和 MemoryPoolAllocator?