【问题标题】:Melting a cast data frame gives incorrect output熔化铸造数据框会产生不正确的输出
【发布时间】:2010-03-03 09:45:15
【问题描述】:

我在reshape 包中的cast/melt 中遇到了一个奇怪的行为。如果我投了data.frame,然后尝试meltmelt 就会出错。从演员data.frame 中手动取消设置“df.melt”类可以使其正确熔化。

有谁知道这是否是预期的行为,如果是,你想要它的用例是什么?

一个显示行为的小代码示例:

> 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

【问题讨论】:

  • 我很困惑。你为什么要melt 一个已经是长格式的df?而且您对cast 的使用也没有多大意义。通常你使用它之后你使用melt
  • 请详细解释一下您尝试执行的操作以及您预期的结果。

标签: r reshape


【解决方案1】:

我知道这是一个老问题,不太可能引起很多兴趣。我也不太明白为什么你正在做你在你的例子中展示的事情。不过,总结一下答案,要么:

  1. 在再次“熔化”之前将df.cast 包裹在as.data.frame 中。
  2. 放弃“reshape”并更新为“reshape2”。这在您发布此问题时不适用,因为您的问题比“reshape2”的第 1 版早了大约半年。

这是一个更长的演练:

首先,我们将加载“reshape”和“reshape2”,执行“强制转换”,并重命名“n”变量。显然,带有“R2”的对象是来自“reshape2”的对象,而“R1”是来自“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"

其次,让我们快速看看我们现在得到了什么:

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

有几点是显而易见的:

  • 通过查看class 的输出,您可以猜测如果您使用“reshape2”,您将不会遇到任何问题
  • 哇哦。 str(df.cast.R1) 的输出是我见过的最奇怪的 data.frame!实际上看起来里面有两个单一变量data.frames。

有了这些新知识,并且在我们不想更改您已转换的data.frameclass 的前提下,让我们继续:

# 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

如果您仍在使用“reshape”中的cast,请考虑升级到“reshape2”,或者围绕melt 编写一个方便的包装函数...也许melt2

melt2 <- function(data, ...) {
  ifelse(isTRUE("cast_df" %in% class(data)), 
         data <- as.data.frame(data), 
         data <- data)
  melt(data, ...)
}

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

【讨论】:

  • @PaulHiemstra,你有什么理由没有切换? (问一个通常坚持使用 base R reshape 来满足他所有重塑需求的人。)
  • 我只是觉得没必要,我主要是用melt为ggplot2或plyr准备数据,不多。
【解决方案2】:

您需要在 之前熔化数据框。铸造而不先熔化会产生各种意想不到的行为,因为 reshape 必须猜测数据的结构。

【讨论】:

    猜你喜欢
    • 2014-07-12
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多