首页 > 解决方案 > 将矩阵转换为三元组 (i,j,v) 的有效方法

问题描述

什么

鉴于一些matrix

mat <- matrix(1:10,ncol=2)

我想将其转换为以下三元组格式: (i,j,v) 其中i是行索引,j是列索引,是 i,j 处的值(您可以在底部v看到原因)

我试过的:

  matrixToTriplet <- function(mat) {
    i <- 1:nrow(mat)
    nj <- ncol(mat)
    j <- 1:nj
    output <- matrix(numeric(0), ncol=3)
    for(i_ in i) {
      curr <- c(rep(i_, times=nj),j,mat[i_,])
      output <- rbind(output, matrix(curr, ncol=3))
    }
    output
  }

输出应该是:

> matrixToTriplet(mat)
      [,1] [,2] [,3]
 [1,]    1    1    1
 [2,]    1    2    6
 [3,]    2    1    2
 [4,]    2    2    7
 [5,]    3    1    3
 [6,]    3    2    8
 [7,]    4    1    4
 [8,]    4    2    9
 [9,]    5    1    5
[10,]    5    2   10

我还有另一个版本使用applyandsapply而不是,for但那些会很快爆炸。我正在处理的尺寸非常大,1600x1600 矩阵。

为什么

有人可能会问“为什么”?原因是我需要is 和js 作为模型预测的特征v。如果有更好的方法来做到这一点,我很想听听。

标签: r

解决方案


你可以用rowand做到这一点col

x <- t(mat)
cbind(c(col(x)), c(row(x)), c(x))
#       [,1] [,2] [,3]
# [1,]    1    1    1
# [2,]    1    2    6
# [3,]    2    1    2
# [4,]    2    2    7
# [5,]    3    1    3
# [6,]    3    2    8
# [7,]    4    1    4
# [8,]    4    2    9
# [9,]    5    1    5
# [10,]    5    2   10

如果最终输出中的行顺序无关紧要,我们也可以cbind(c(row(mat)), c(col(mat)), c(mat))直接使用。

在谈论效率时,基准会有所帮助:

library(microbenchmark)
bmf <- function(mat, ...){
    microbenchmark(
        a = {x <- t(mat);cbind(c(col(x)), c(row(x)), c(x))},
        a2 = {cbind(c(row(mat)), c(col(mat)), c(mat))},
        b = {cbind(which(mat > 0, arr.ind = TRUE), val = c(mat))},
        c = {cbind(expand.grid(seq(nrow(mat)), seq(ncol(mat))), as.vector(mat))},
        ...)
}

mat <- matrix(seq_len(10*10), 10, 10)
bmf(mat, times = 10)
# Unit: microseconds
#  expr     min      lq     mean   median      uq     max neval
#     a   7.985   9.239  18.2556  15.0415  22.756  47.065    10
#    a2   4.310   4.681   5.5257   5.2405   5.755   9.099    10
#     b  17.032  21.672  35.8950  28.7505  59.170  68.436    10
#     c 216.101 228.736 267.7217 243.9465 288.455 380.096    10'


mat <- matrix(seq_len(1000*1000), 1000, 1000)
bmf(mat, times = 10)

# Unit: milliseconds
#  expr      min       lq     mean   median        uq      max neval
#     a 17.70805 20.51167 36.73432 21.79357  24.56775 111.6796    10
#    a2 14.61793 20.95486 37.70526 25.58968 30.91322  98.44344    10
#     b 41.74630 45.49698 76.61307 47.86678 122.90142 178.8363    10
#     c 14.40912 17.84025 25.39672 19.29968  20.12222  85.2515    10

推荐阅读