【问题标题】:convert from sparse Matrix to dense matrix without losing dimnames?从稀疏矩阵转换为密集矩阵而不丢失暗名?
【发布时间】:2021-09-05 16:11:16
【问题描述】:

将稀疏的 Matrix 对象(来自 Matrix 包)转换为普通的旧 base-R 密集 matrix 对象似乎会丢失行/列名称。

m <- matrix(0, 3,3, dimnames = list(LETTERS[1:3], LETTERS[1:3]))
dimnames(m)
## [[1]]
## [1] "A" "B" "C"
## 
## [[2]]
## [1] "A" "B" "C"

转换 Matrix 没问题:

dimnames(M <- Matrix::Matrix(m))
## [[1]]
## [1] "A" "B" "C"
## [[2]]
## [1] "A" "B" "C"

但转换回来似乎会丢失行/列名称:

dimnames(as.matrix(M))
## NULL
dimnames(as(M, "matrix"))
## NULL

我知道我可以通过存储暗名称然后将它们附加到新对象来解决它(见下文),但我觉得我不应该这样做......我是否缺少透明/更好的方式进行转换,或者在进行此转换时应该保留暗名的逻辑原因??

## workaround/hack
dn <- dimnames(m)
m2 <- as.matrix(M)
dimnames(m2) <- dn

为了澄清,我想处理 M 已经存在的情况 m 还没有 (即旧的 m[] &lt;- 技巧替换 @987654332 的内容@ 而保持其属性不变似乎不起作用...)

【问题讨论】:

  • Bug 现已修复,位于Matrix r3418。下一个版本应该包含补丁。
  • 谢谢你,米凯尔。 (特别是报告)。而 Matrix 1.4-0 确实在昨天发布到了 CRAN。

标签: r matrix sparse-matrix


【解决方案1】:

[更新 1:bug report] [更新 2:patch]

这里[dD]imnames的丢失似乎是Matrix中的一个错误,至少在相关"Matrix"的特定子类的实现中,即"ddiMatrix"(参见?`ddiMatrix-class`)。

library("Matrix")
M <- Matrix(0, 3L, 3L, dimnames = list(LETTERS[1:3], LETTERS[1:3]))
M
3 x 3 diagonal matrix of class "ddiMatrix"
  A B C
A 0 . .
B . 0 .
C . . 0

有一种将"ddiMatrix" 强制转换为"matrix" 的方法,当您执行as(M, "matrix") 时会调用该方法,但正如您所观察到的,它不会保留[dD]imnames

selectMethod("coerce", signature(from = "ddiMatrix", to = "matrix"))
Method Definition:

function (from, to = "matrix", strict = TRUE) 
base::diag(if (from@diag == "U") as1(from@x) else from@x, nrow = from@Dim[1])
<bytecode: 0x11e7dc068>
<environment: namespace:Matrix>

Signatures:
        from        to      
target  "ddiMatrix" "matrix"
defined "ddiMatrix" "matrix"

您可以使用从"ddiMatrix""dgCMatrix" 的中间强制来解决该错误,这是一种更通用且实现更仔细的稀疏数字矩阵类(请参阅?`dgCMatrix-class`)。从"ddiMatrix""dgCMatrix""matrix" 的强制转换保留[dD]imnames:

MM <- as(M, "dgCMatrix")
MM
3 x 3 sparse Matrix of class "dgCMatrix"
  A B C
A . . .
B . . .
C . . .
m <- as(MM, "matrix")
m
  A B C
A 0 0 0
B 0 0 0
C 0 0 0

或者只是m &lt;- as(as(M, "dgCMatrix"), "matrix")

明确地说,您的方法既更快更透明。我提出这个主要是为了揭露这个错误影响"ddiMatrix" 但不是Matrix 中实现的所有稀疏数字矩阵类的事实。如果您的用例实际上不需要"ddiMatrix",那么您不必担心自己保留[dD]imnames

FWIW,在处理 Matrix 强制时,我发现它有助于:

  1. 使用showClass("Matrix") 提醒自己"Matrix" 子类的继承结构。
  2. 请咨询 ?`&lt;classname&gt;-class`,了解 (1) 中报告的类及其插槽的可读描述。
  3. 使用selectMethod("coerce", signature(from=, to=)) 来查找as 实际调用的方法(不过,由于强制转换通常在C 中实现,所以selectMethod 结果除了告诉我要在Matrix/src 中搜索什么之外可能没有任何帮助。

【讨论】:

    【解决方案2】:

    看起来“m”和“M”的区别在于对象类型:

    m <- matrix(0, 3,3, dimnames = list(LETTERS[1:3], LETTERS[1:3]))
    M <- Matrix::Matrix(m)
    
    typeof(m)
    #> [1] "double"
    
    typeof(M)
    #> [1] "S4"
    

    我不知道是否有“简单”的方法,但另一种选择可能是:

    m <- matrix(0, 3,3, dimnames = list(LETTERS[1:3], LETTERS[1:3]))
    dimnames(m)
    #> [[1]]
    #> [1] "A" "B" "C"
    #> 
    #> [[2]]
    #> [1] "A" "B" "C"
    M <- Matrix::Matrix(m)
    m <- as.matrix(M)
    dimnames(m) <- M@Dimnames
    m
    #>   A B C
    #> A 0 0 0
    #> B 0 0 0
    #> C 0 0 0
    

    或许:

    m <- matrix(M, nrow = M@Dim, dimnames = M@Dimnames)
    m
    #>   A B C
    #> A 0 0 0
    #> B 0 0 0
    #> C 0 0 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-25
      • 2023-04-10
      • 2021-11-25
      • 2017-07-02
      • 2013-03-07
      • 1970-01-01
      • 2014-03-06
      • 2021-02-23
      相关资源
      最近更新 更多