对于具有命名行/列的矩阵,reshape2::melt() 的替代方案?

问题描述 投票:0回答:1

melt()
包中的
reshape2
函数有一个方便的行为,它将具有命名行/列的矩阵转换为三列数据框,其中矩阵行/列名称成为前两列:

testmat <- matrix(1:25,nrow=5,dimnames=list(LETTERS[6:10],LETTERS[1:5]))
#   A  B  C  D  E
# F 1  6 11 16 21
# G 2  7 12 17 22
# H 3  8 13 18 23
# I 4  9 14 19 24
# J 5 10 15 20 25

longmat <- reshape2::melt(testmat)
head(longmat)
# Var1 Var2 value
#    F    A     1
#    G    A     2
#    H    A     3
#    I    A     4
#    J    A     5
#    F    B     6

但是它有令人讨厌的行为,即生成 Var1 和 Var2 因子,并且它不支持

stringsAsFactors=F
选项。 reshape2 的 README 表示“reshape2 已退役:只会进行将其保留在 CRAN 上所需的更改。我们建议改用 tidyr。”,因此这种行为似乎不太可能在
melt()
中改变。

我已经尝试过替代方案,但还没有找到有效的方法:

  • tidyr::pivot_longer()
    不会将矩阵作为输入。即使我强制矩阵成为带有
    tidyr::pivot_longer(as.data.frame(testmat),cols=all_of(colnames(testmat)))
    的 data.frame,矩阵行名称也会被丢弃,而不是捕获在结果的列中。
  • data.table::melt()
    只是重定向到
    reshape2::melt()

主要问题:是否有其他函数(tidyverse或非tidyverse)可以以类似于

reshape2::melt()
的方式将矩阵转换为长形式?

第二个问题:我一直在尝试自己编写。是否有任何我没有想到的隐藏“陷阱”可能会使下面的函数产生意外/不正确的行为?

melt_by_hand <- function(mat) {
  return(data.frame(row=rep(rownames(mat),ncol(mat)),
                      col=rep(colnames(mat),each=nrow(mat)),
                      value=as.vector(mat)))
}
r tidyr reshape2 melt
1个回答
0
投票

转换为data.table,然后融化:

melt(data.table(testmat, keep.rownames = TRUE), id.vars = "rn", variable.factor = FALSE)
#        rn variable value
#    <char>   <char> <int>
# 1:      F        A     1
# 2:      G        A     2
# 3:      H        A     3
# ....
© www.soinside.com 2019 - 2024. All rights reserved.