【问题标题】:fast melt large 2d matrix to 3 column data.table快速将大型 2d 矩阵融化为 3 列 data.table
【发布时间】:2020-09-24 13:26:07
【问题描述】:

我有一个大矩阵num [1:62410, 1:48010]

我想要一个长格式的data.table

例如

   Var1 Var2     value
1:    1    1 -4227.786
2:    2    1 -4211.908
3:    3    1 -4197.034
4:    4    1 -4183.645
5:    5    1 -4171.692
6:    6    1 -4161.634

小例子

m = matrix(1:5, nrow = 1000, ncol = 1000)
x = data.table(reshape2::melt(m))

理想情况下,我希望列名 x、y 和 value 同时出现。

以前我一直在使用data.table(melt(mymatrix))。 但是从 reshape2::melt 已弃用的警告来看,这在速度方面可能不是最佳的,解决这个问题的最佳“data.table”方法是什么?

以下内容不能回答我的问题: Fast melted data.table operations Proper/fastest way to reshape a data.table

其他答案参考已弃用的reshape2

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    这是一个例子:

    # example matrix
    m = matrix(1:12, nrow = 4)
    
    # load data table
    library(data.table)
    

    我们可以直接提取数据,行和列信息,应该很快:

    dt = data.table(
      row = rep(seq_len(nrow(m)), ncol(m)), 
      col = rep(seq_len(ncol(m)), each = nrow(m)), 
      value = c(m)
    )
    

    结果是:

        row col value
     1:   1   1     1
     2:   2   1     2
     3:   3   1     3
     4:   4   1     4
     5:   1   2     5
     6:   2   2     6
     7:   3   2     7
     8:   4   2     8
     9:   1   3     9
    10:   2   3    10
    11:   3   3    11
    12:   4   3    12
    

    【讨论】:

      【解决方案2】:

      array 有一个 as.data.table 方法可以为您解决问题。

      dim(m) <- c(dim(m), 1L)
      as.data.table(m)
      

      以后,在发布关于 SO 的问题时,请提供最简单的示例。

      我现在查看了它的来源,我发现它可能不是很有效,因为它会具体化所有 NA 值,然后将它们删除。

      【讨论】:

      • 融化data.table 不是更快吗? d = as.data.table(m); d[ , ri := 1:.N]; melt(d, id.vars = "ri")。测试例如nr = 1e4; nc = 1e4; m = matrix(1:(nr*nc), nrow = nr)
      • Henrik,这导致称为变量的字符列,而不是我想要的输出。 (我需要去掉“V”并进行类型转换)
      • jangorecki,谢谢,但乍一看,这比 reshape2::melt 方法慢了 2-3 倍。
      • 很高兴知道,我知道它并没有真正针对速度进行优化。这不会经常出现。如果您愿意,请随时在 data.table 存储库中提交 FR 以加快速度。
      • @BetaScoo8 抱歉,我在阅读您想要的输出时很草率 :) 尝试:dimnames(m) &lt;- list(NULL, 1:ncol(m)); d = as.data.table(m); d[ , ri := 1:.N]; d2 = melt(d, id.vars = "ri", variable.name = "ci"); d2[ , ci := as.integer(ci)]。尽管有两个额外的步骤(dimnamesas.integer),我认为它仍然更快。
      【解决方案3】:

      不久前,我遇到了与@BetaScoo8 相同的问题,并提出了类似的问题(see here)。正如@jangorecki as.data.table "melts" 数组而不是矩阵(2D)所指出的那样。

      # 2D matrix
      > AR <- array(1:12, dim = c(3,4))
      > DT <- as.data.table(AR)
      > print(DT) # Note: no "value" column, matrix str is preserved!
         V1 V2 V3 V4
      1:  1  4  7 10
      2:  2  5  8 11
      3:  3  6  9 12
      
      # 3D array
      > AR <- array(1:24, dim=c(3,4,2))
      > DT <- as.data.table(AR)
      > print(DT)
          V1 V2 V3 value
       1:  1  1  1     1
       2:  1  1  2    13
       3:  1  2  1     4
       4:  1  2  2    16
      [...]
      21:  3  3  1     9
      22:  3  3  2    21
      23:  3  4  1    12
      24:  3  4  2    24
          V1 V2 V3 value
      > 
      

      所以,我编写了一个函数,以同样的方式灵活地将矩阵或数组转换为 data.table。也许对其他人有帮助。

      # Melt matrix or array to data.table 
      array2dataTable <- function(x) {
        
        # if is matrix, add third dimension (as.data.table does not melt matrices)
        x.is.matrix <- FALSE
        if (length(dim(x))==2) {
          x.is.matrix <- TRUE
          cat("\nNote: x is a matrix, converting it to array with 3rd dim==3 ..")
          dim(x) <- c(dim(x), 1L)
        }
        # add dimnames
        if (is.null(dimnames(x))) {
          cat("\nNote: Array has no dimnames, using seq of integers ..\n")
          dimnames(x) <- lapply(dim(x), function(X) as.character(seq.int(1, X)))
        }
        DT <- as.data.table(x, na.rm = TRUE)
        if (x.is.matrix==TRUE) DT[,V3:=NULL] # remove third column if converting from 2D matrix
        print(str(DT))
        return(DT)
      }
      

      如果您发现此问题有任何问题,很高兴获得反馈。谢谢!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 2017-04-21
        • 2015-10-11
        • 2021-10-26
        • 2018-05-05
        • 1970-01-01
        相关资源
        最近更新 更多