在不丢失 dimnames 的情况下从稀疏矩阵转换为密集矩阵?
convert from sparse Matrix to dense matrix without losing dimnames?
将稀疏 Matrix
对象(来自 Matrix
包)转换为普通的旧 base-R 密集 matrix
对象似乎丢失了 row/column 名称。
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"
但是转换回来似乎失去了 row/column 名字:
dimnames(as.matrix(M))
## NULL
dimnames(as(M, "matrix"))
## NULL
我知道我可以通过存储 dimnames 然后将它们附加到新对象来解决这个问题(见下文),但我觉得我不应该这样做......我是否错过了 transparent/better 进行转换的方式,或者为什么 dimnames 在进行此转换时 不 应该保留的逻辑原因??
## workaround/hack
dn <- dimnames(m)
m2 <- as.matrix(M)
dimnames(m2) <- dn
澄清一下,我想处理 M
已经存在的情况 但 m
还没有 (即旧的 m[] <-
替换 m
的内容同时保持其属性不变的技巧似乎不起作用 ...)
看起来“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"
我不知道是否有 'easy' 方法,但另一种选择可能是:
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
[更新 1:bug report]
[更新 2:patch]
这里[dD]imnames
的丢失似乎是Matrix
中的一个错误,至少在"Matrix"
的特定子class的实现中是这样,即"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"
的中间强制转换来解决该错误,这是一个更通用且更仔细实现的 class 稀疏数字矩阵(请参阅 ?`dgCMatrix-class`
).从 "ddiMatrix"
到 "dgCMatrix"
到 "matrix"
do 的强制保留 [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 <- as(as(M, "dgCMatrix"), "matrix")
.
需要说明的是,您的方法更快 并且 更透明。我介绍这个主要是为了揭露这个错误影响 "ddiMatrix"
但不是 Matrix
中实现的稀疏数字矩阵的所有 classes 的事实。如果您的用例实际上不需要 "ddiMatrix"
,那么您不必担心自己会保留 [dD]imnames
。
FWIW,在与 Matrix
强制转换作斗争时,我发现它有助于:
- 使用
showClass("Matrix")
提醒自己"Matrix"
子classes的继承结构。
- 请参阅
?`<classname>-class`
以了解 (1) 中报告的 classes 及其位置的人类可读描述。
- 使用
selectMethod("coerce", signature(from=, to=))
找到 as
实际调用的方法(尽管,由于强制转换通常在 C 中实现,selectMethod
结果除了告诉我要做什么之外可能没有帮助在 Matrix/src
). 中搜索
将稀疏 Matrix
对象(来自 Matrix
包)转换为普通的旧 base-R 密集 matrix
对象似乎丢失了 row/column 名称。
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"
但是转换回来似乎失去了 row/column 名字:
dimnames(as.matrix(M))
## NULL
dimnames(as(M, "matrix"))
## NULL
我知道我可以通过存储 dimnames 然后将它们附加到新对象来解决这个问题(见下文),但我觉得我不应该这样做......我是否错过了 transparent/better 进行转换的方式,或者为什么 dimnames 在进行此转换时 不 应该保留的逻辑原因??
## workaround/hack
dn <- dimnames(m)
m2 <- as.matrix(M)
dimnames(m2) <- dn
澄清一下,我想处理 M
已经存在的情况 但 m
还没有 (即旧的 m[] <-
替换 m
的内容同时保持其属性不变的技巧似乎不起作用 ...)
看起来“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"
我不知道是否有 'easy' 方法,但另一种选择可能是:
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
[更新 1:bug report] [更新 2:patch]
这里[dD]imnames
的丢失似乎是Matrix
中的一个错误,至少在"Matrix"
的特定子class的实现中是这样,即"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"
的中间强制转换来解决该错误,这是一个更通用且更仔细实现的 class 稀疏数字矩阵(请参阅 ?`dgCMatrix-class`
).从 "ddiMatrix"
到 "dgCMatrix"
到 "matrix"
do 的强制保留 [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 <- as(as(M, "dgCMatrix"), "matrix")
.
需要说明的是,您的方法更快 并且 更透明。我介绍这个主要是为了揭露这个错误影响 "ddiMatrix"
但不是 Matrix
中实现的稀疏数字矩阵的所有 classes 的事实。如果您的用例实际上不需要 "ddiMatrix"
,那么您不必担心自己会保留 [dD]imnames
。
FWIW,在与 Matrix
强制转换作斗争时,我发现它有助于:
- 使用
showClass("Matrix")
提醒自己"Matrix"
子classes的继承结构。 - 请参阅
?`<classname>-class`
以了解 (1) 中报告的 classes 及其位置的人类可读描述。 - 使用
selectMethod("coerce", signature(from=, to=))
找到as
实际调用的方法(尽管,由于强制转换通常在 C 中实现,selectMethod
结果除了告诉我要做什么之外可能没有帮助在Matrix/src
). 中搜索