【问题标题】:R: transforming "short form" data to "long form" data without for loops?R:在没有 for 循环的情况下将“短格式”数据转换为“长格式”数据?
【发布时间】:2011-05-04 00:28:34
【问题描述】:

假设我有一个像这样的 R 数据框:

  Subject Session  Property.A Property.B Property.C
1     100       1 -1.22527548 -0.9193751 -1.7501693
2     100      10  2.30627980  1.8940830 -0.8443976
3     100       2  2.33243332 -0.5860868 -4.2074489
4     100       3  0.38130810 -0.7336206  4.8016230
5     100       4  1.44685875  0.5066249  2.0138624
6     100       5  0.08907721 -0.3715202  1.4983700

我听说过这种风格的数据框被称为“短格式”或“宽格式”。现在假设我想让它看起来像这样,我听说它被称为“长格式”:

  Subject Session  Property    Value
1     100       1         A   -1.2252754
2     100       1         B   -0.9193751
3     100       1         C   -1.7501693
4     100       2         A    2.3324333
5     100       2         B   -0.5860868
6     100       2         C   -4.2074489

也就是说,我有 N 列我想减少到两个“名称/值”列,数据框中的任何其他列都根据需要使用重复值进行扩展。

显然我可以用一堆 for 循环来执行这种转换,但这看起来真的很难看,如果/当我添加更多属性列时维护会很痛苦。

有没有办法在 R 中只用几行代码就可以做到这一点?一些我还没有发现的神奇功能组合?

【问题讨论】:

  • 更新:如今,我变得聪明了,我使用plyr 来满足我所有的数据重塑需求!
  • 在 plyr 中有什么方法可以做到这一点?

标签: r dataframe


【解决方案1】:

使用包reshape2中的melt函数:

library(reshape2)
dat.m <- melt(dat, id.vars = c("Subject", "Session"))

如果您需要清理变量列的列名和/或值:

#change "variable" to "Property"
names(dat.m)[3] <- "Property"
#Drop "Property." from the column values
dat.m$Property <- gsub("Property\\.", "", dat.m$Property)

【讨论】:

  • 谢谢,就是这样。我现在正在查看 reshape 包文档,这是一个多么棒的概念。不知道我怎么会通过搜索找到它,不过,使用诸如“熔化”、“熔化”和“铸造”等纯粹隐喻、非描述性的术语。这似乎是一件很常见的事情,怎么可能不成为基本 R 功能的一部分?
  • stats 中的 reshape 函数带有基本 R 并提供看似等效的功能来熔化和铸造,尽管我从未尝试过学习它,因为 meltcast 的语法是很容易上手。至于搜索东西,我想你确实有点意思 - 幸运的是!
  • 或者使用reshape2 会快很多
【解决方案2】:

我喜欢使用 plyr 函数,但是 base 中的 reshape 函数非常强大,如下面的解决方案所示。

# create a dummy data frame
dat = data.frame(
  subject = rep(100, 5),
  session = sample(5, 10, replace = T),
  property.a = rnorm(5),
  property.b = rnorm(5),
  property.c = rnorm(5)
)

# convert wide to long, varying columns are 3:5, separator is "."
dat.long = reshape(dat, direction = 'long', varying = 3:5, sep = ".")

【讨论】:

  • 为此 +1。我花了 10 分钟试图让这项工作作为替代方法发布在我的答案中,但一直陷入困境。
【解决方案3】:

reshape package for this 非常适合,但是......一堆循环不是替代品。

也许这个例子很有启发性……

longDF <- lapply( 3:4, function(x) cbind(wideDF[1:2], p = names(wideDF)[x], wideDF[x]) )
longDF <- rbind( longDF )

或者这个

longDF <- cbind( rep(wideDF[1], 3), rep(wideDF[2], 3), c(wideDF[3], wideDF[4], wideDF[5]) )

【讨论】:

    猜你喜欢
    • 2023-02-25
    • 2021-11-16
    • 2013-10-22
    • 2021-10-08
    相关资源
    最近更新 更多