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)))
}
转换为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
# ....