Derreter um quadro de dados fundido fornece saída incorreta
Pergunta
Eu encontrei um comportamento estranho em cast
/melt
de reshape
pacote.Se eu lançar um data.frame
, e então tente melt
isso, o melt
sai errado.Desativando manualmente a classe "df.melt" do elenco data.frame
permite que seja derretido corretamente.
Alguém sabe se esse é o comportamento pretendido e, em caso afirmativo, qual é o caso de uso quando você deseja?
Um pequeno exemplo de código que mostra o comportamento:
> df <- data.frame(type=c(1, 1, 2, 2, 3, 3), variable="n", value=c(71, 72, 68, 80, 21, 20))
> df
type variable value
1 1 n 71
2 1 n 72
3 2 n 68
4 2 n 80
5 3 n 21
6 3 n 20
> df.cast <- cast(df, type~., sum)
> names(df.cast)[2] <- "n"
> df.cast
type n
1 1 143
2 2 148
3 3 41
> class(df.cast)
[1] "cast_df" "data.frame"
> melt(df.cast, id="type", measure="n")
type value value
X.all. 1 143 (all)
X.all..1 2 148 (all)
X.all..2 3 41 (all)
> class(df.cast) <- "data.frame"
> class(df.cast)
[1] "data.frame"
> melt(df.cast, id="type", measure="n")
type variable value
1 1 n 143
2 2 n 148
3 3 n 41
Solução
Eu sei que esta é uma pergunta ANTIGA e provavelmente não gerará muito interesse.Eu também não consigo entender por que você está fazendo o que demonstra em seu exemplo.No entanto, para resumir a resposta:
- Embrulhe seu
df.cast
emas.data.frame
antes de "derreter" novamente. - Abandone "reshape" e atualize para "reshape2".Isso não era aplicável quando você postou esta pergunta, já que ela é anterior à versão 1 de "reshape2" em cerca de meio ano.
Aqui está um passo a passo mais longo:
Primeiro, carregaremos "reshape" e "reshape2", realizaremos sua "casting" e renomearemos sua variável "n".Obviamente, os objetos anexados com "R2" são aqueles de "reshape2" e "R1", de "reshape".
library(reshape)
library(reshape2)
df.cast.R2 <- dcast(df, type~., sum)
df.cast.R1 <- cast(df, type~., sum)
names(df.cast.R1)[2] <- "n"
names(df.cast.R2)[2] <- "n"
Em segundo lugar, vamos dar uma rápida olhada no que temos agora:
class(df.cast.R1)
# [1] "cast_df" "data.frame"
class(df.cast.R2)
[1] "data.frame"
str(df.cast.R1)
# List of 2
# $ type: num [1:3] 1 2 3
# $ n : num [1:3] 143 148 41
# - attr(*, "row.names")= int [1:3] 1 2 3
# - attr(*, "idvars")= chr "type"
# - attr(*, "rdimnames")=List of 2
# ..$ :'data.frame': 3 obs. of 1 variable:
# .. ..$ type: num [1:3] 1 2 3
# ..$ :'data.frame': 1 obs. of 1 variable:
# .. ..$ value: Factor w/ 1 level "(all)": 1
str(df.cast.R2)
# 'data.frame': 3 obs. of 2 variables:
# $ type: num 1 2 3
# $ n : num 143 148 41
Algumas observações são óbvias:
- Olhando para a saída de
class
, você pode adivinhar que você não terá problemas em fazer o que está tentando fazer se estiver usando "reshape2" - Uau.Essa saída de
str(df.cast.R1)
é a aparência mais estranhadata.frame
Que eu já vi!Na verdade, parece que existem duas variáveis únicasdata.frame
está aí.
Com estes novos conhecimentos, e com a condição de que não queremos alterar o class
do seu elenco data.frame
, vamos prosseguir:
# You don't want this
melt(df.cast.R1, id="type", measure="n")
# type value value
# X.all. 1 143 (all)
# X.all..1 2 148 (all)
# X.all..2 3 41 (all)
# You *do* want this
melt(as.data.frame(df.cast.R1), id="type", measure="n")
# type variable value
# 1 1 n 143
# 2 2 n 148
# 3 3 n 41
# And the class has not bee altered
class(df.cast.R1)
# [1] "cast_df" "data.frame"
# As predicted, this works too.
melt(df.cast.R2, id="type", measure="n")
# type variable value
# 1 1 n 143
# 2 2 n 148
# 3 3 n 41
Se você ainda está trabalhando com cast
de "reshape", considere atualizar para "reshape2" ou escreva uma função wrapper conveniente em torno melt
...talvez melt2
?
melt2 <- function(data, ...) {
ifelse(isTRUE("cast_df" %in% class(data)),
data <- as.data.frame(data),
data <- data)
melt(data, ...)
}
Experimente df.cast.R1
:
melt2(df.cast.R, id="type", measure="n")
# ype variable value
# 1 1 n 143
# 2 2 n 148
# 3 3 n 41
Outras dicas
Você precisa derreter o quadro de dados antes da você lançou. O lançamento sem derreter primeiro produzirá todos os tipos de comportamento inesperado, porque o RESHAPE precisa adivinhar a estrutura de seus dados.