A melt()
função do reshape2
pacote tem um comportamento conveniente, pois converte uma matriz com linhas/colunas nomeadas em um quadro de dados de três colunas, com os nomes das linhas/colunas da matriz se tornando as duas primeiras colunas:
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
Mas ele tem o comportamento irritante de fazer fatores Var1 e Var2, e não suporta uma stringsAsFactors=F
opção. O README para reshape2 diz "reshape2 foi aposentado: somente as mudanças necessárias para mantê-lo no CRAN serão feitas. Recomendamos usar tidyr em vez disso.", então parece improvável que esse comportamento seja alterado em melt()
.
Experimentei alternativas, mas ainda não encontrei nada que funcione:
tidyr::pivot_longer()
não aceitará uma matriz como entrada. Mesmo se eu forçar a matriz a se tornar um data.frame comtidyr::pivot_longer(as.data.frame(testmat),cols=all_of(colnames(testmat)))
, os nomes das linhas da matriz serão descartados em vez de capturados em uma coluna no resultado.data.table::melt()
apenas redireciona parareshape2::melt()
.
Pergunta principal: Existe alguma outra função (tidyverse ou não tidyverse) que converterá uma matriz para o formato longo de maneira semelhante a reshape2::melt()
?
Segunda pergunta: Tenho experimentado escrever o meu próprio. Há alguma "pegadinha" escondida que eu não tenha pensado que pode fazer a função abaixo produzir comportamentos inesperados/incorretos?
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)))
}
Nada mais além
as.data.frame.table
da base R deve ajudarConverta para data.table e depois derreta: