【问题标题】:How to convert data.frame to (flat) matrix?如何将 data.frame 转换为(平面)矩阵?
【发布时间】:2012-05-01 21:27:45
【问题描述】:

如何将下面的 data.frame 转换为给定的矩阵? data.frame 的前两列包含行变量,其他列的所有组合(包含值的列除外)确定列。理想情况下,我正在寻找一个不需要更多软件包的解决方案(所以 no reshape2 解决方案)。另外,没有ftable 解决方案。

(df <- data.frame(c1=rep(c(1, 2), each=8), c2=rep(c(1, 2, 1, 2), each=4),
                  gr=rep(c(1, 2), 8), subgr=rep(c(1,2), 4, each=2), val=1:16) )

c1 c2 gr1.subgr1 gr1.subgr2 gr2.subgr1 gr2.subgr2
1  1   1          3          2          4
1  2   5          7          6          8
2  1   9         11         10         12
2  2  13         15         14         16

【问题讨论】:

  • 总是有基本函数reshape,我一直不够聪明,无法理解它的论点,但我也不是一个贪吃痛苦的人,所以我通常使用reshape2,因为它是一致性和易用性。 YMMV
  • reshape 和 reshape2 是用 base R 编写的,所以如果你想在不加载包的情况下使用它们的方法,只需提取函数内容(例如,键入 acast 并复制函数内容)

标签: r


【解决方案1】:

使用交互变量来构建组:

newdf <- reshape(df, idvar=1:2, direction="wide", 
            timevar=interaction(df$gr,df$subgr) , 
            v.names="val", 
            drop=c("gr","subgr") ) 
names(newdf)[3:6] <- c("gr1.subgr1", "gr1.subgr2", "gr2.subgr1",  "gr2.subgr2")
 newdf
   c1 c2 gr1.subgr1 gr1.subgr2 gr2.subgr1 gr2.subgr2
1   1  1          1          2          3          4
5   1  2          5          6          7          8
9   2  1          9         10         11         12
13  2  2         13         14         15         16

【讨论】:

  • +1 - 没看过/我忘了interaction()。可能比手动构建要好得多。
  • 这行得通,谢谢 DWin。我在我原来的问题中构建了它。我有一个完全相同类型的 data.frame(如str() 所示)。问题是我得到Error in [.data.frame(data, , timevar) : undefined columns selected,不知道怎么回事……
  • 你能用一个小子集让它有这个错误,然后发布 dput 输出吗? (我刚刚在新的会话中再次运行它,没有出现错误。)
【解决方案2】:

好的 - 这看起来大部分都是你想要的。从阅读帮助文件来看,这似乎应该做你想做的事:

reshape(df, idvar = c("c1", "c2"), timevar = c("gr", "subgr")
        , direction = "wide")
   c1 c2 val.c(1, 2, 1, 2) val.c(1, 1, 2, 2)
1   1  1                NA                NA
5   1  2                NA                NA
9   2  1                NA                NA
13  2  2                NA                NA

我无法完全解释为什么它会显示为 NA 值。但是,也许帮助页面中的这一点解释了:

timevar 
the variable in long format that differentiates multiple records from the same 
group or individual. If more than one record matches, the first will be taken.

我最初认为这意味着如果您给它的列名有歧义,R 将使用它的部分匹配功能,但也许不是?接下来,我尝试将grsubgr 合并到一个列中:

df$newcol <- with(df, paste("gr.", gr, "subgr.", subgr, sep = ""))

让我们再试一次:

reshape(df, idvar = c("c1", "c2"), timevar = "newcol"
        , direction = "wide", drop= c("gr","subgr"))

   c1 c2 val.gr.1subgr.1 val.gr.2subgr.1 val.gr.1subgr.2 val.gr.2subgr.2
1   1  1               1               2               3               4
5   1  2               5               6               7               8
9   2  1               9              10              11              12
13  2  2              13              14              15              16

快!我无法解释或弄清楚如何使它不将val. 附加到列名,但我会让你自己弄清楚。我确定它在某处的帮助页面上。它还将组的顺序与您要求的不同,但数据似乎是正确的。

FWIW,这是reshape2 的解决方案

> dcast(c1 + c2 ~ gr + subgr, data = df, value.var = "val")
  c1 c2 1_1 1_2 2_1 2_2
1  1  1   1   3   2   4
2  1  2   5   7   6   8
3  2  1   9  11  10  12
4  2  2  13  15  14  16

虽然你仍然需要清理列名。

【讨论】:

  • 有趣!我在 R 的早期使用 paste("grp","subgrp") 方法到 reshape() 并认为这看起来很奇怪。你让我相信我没有疯,我应该学会使用reshape2
  • dcast的版本确实不错。也可以使用acast
猜你喜欢
  • 1970-01-01
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-06
  • 2017-12-22
相关资源
最近更新 更多