首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用多个度量值列将数据从长格式转换为宽格式

使用多个度量值列将数据从长格式转换为宽格式
EN

Stack Overflow用户
提问于 2012-05-15 02:33:14
回答 5查看 40.5K关注 0票数 44

当我要携带多个度量变量时,我很难找出将数据从长格式转换为宽格式的最优雅和灵活的方法。

例如,这是一个长格式的简单数据帧。ID是主题,TIME是时间变量,XYTIMEID测量值

代码语言:javascript
复制
> my.df <- data.frame(ID=rep(c("A","B","C"), 5), TIME=rep(1:5, each=3), X=1:15, Y=16:30)
> my.df

   ID TIME  X  Y
1   A    1  1 16
2   B    1  2 17
3   C    1  3 18
4   A    2  4 19
5   B    2  5 20
6   C    2  6 21
7   A    3  7 22
8   B    3  8 23
9   C    3  9 24
10  A    4 10 25
11  B    4 11 26
12  C    4 12 27
13  A    5 13 28
14  B    5 14 29
15  C    5 15 30

如果我只想将TIME的值转换为包含X的列标题,我知道我可以使用reshape包中的cast() (或reshape2中的dcast() ):

代码语言:javascript
复制
> cast(my.df, ID ~ TIME, value="X")
  ID 1 2 3  4  5
1  A 1 4 7 10 13
2  B 2 5 8 11 14
3  C 3 6 9 12 15

但我真正想做的也是引入Y作为另一个度量变量,并让列名同时反映度量变量名称和时间值:

代码语言:javascript
复制
  ID X_1 X_2 X_3  X_4 X_5 Y_1 Y_2 Y_3 Y_4 Y_5
1  A   1   4   7   10  13  16  19  22  25  28
2  B   2   5   8   11  14  17  20  23  26  29
3  C   3   6   9   12  15  18  21  24  27  30

(顺便说一句,我真的不在乎所有的X是不是都跟在Y后面,或者它们是不是像X_1Y_1X_2Y_2等一样交错。)

我可以通过转换两次长数据并合并结果来接近这一点,尽管列名需要一些工作,如果我需要在XY之外添加第三个或第四个变量,我将需要调整它

代码语言:javascript
复制
merge(
cast(my.df, ID ~ TIME, value="X"),
cast(my.df, ID ~ TIME, value="Y"),
by="ID", suffixes=c("_X","_Y")
)

似乎reshape2和/或plyr中的一些函数组合应该能够比我的尝试更优雅地做到这一点,以及更干净地处理多个度量变量。像cast(my.df, ID ~ TIME, value=c("X","Y"))这样的东西,它是无效的。但我一直没能弄明白。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-05-15 03:17:44

为了像你想要的那样处理多个变量,你需要在对数据进行类型转换之前对它进行melt

代码语言:javascript
复制
library("reshape2")

dcast(melt(my.df, id.vars=c("ID", "TIME")), ID~variable+TIME)

这给了我们

代码语言:javascript
复制
  ID X_1 X_2 X_3 X_4 X_5 Y_1 Y_2 Y_3 Y_4 Y_5
1  A   1   4   7  10  13  16  19  22  25  28
2  B   2   5   8  11  14  17  20  23  26  29
3  C   3   6   9  12  15  18  21  24  27  30

基于注释进行编辑:

数据帧

代码语言:javascript
复制
num.id = 10 
num.time=10 
my.df <- data.frame(ID=rep(LETTERS[1:num.id], num.time), 
                    TIME=rep(1:num.time, each=num.id), 
                    X=1:(num.id*num.time), 
                    Y=(num.id*num.time)+1:(2*length(1:(num.id*num.time))))

给出不同的结果(所有条目都是2),因为ID/TIME组合不指示唯一行。实际上,每种ID/TIME组合都有两行。reshape2假设每个可能的变量组合都有一个值,如果有多个条目,则将应用汇总函数来创建单个变量。这就是为什么会有这样的警告

代码语言:javascript
复制
Aggregation function missing: defaulting to length

如果你添加另一个变量来打破这种冗余,你就可以得到一些有用的东西。

代码语言:javascript
复制
my.df$cycle <- rep(1:2, each=num.id*num.time)
dcast(melt(my.df, id.vars=c("cycle", "ID", "TIME")), cycle+ID~variable+TIME)

这之所以有效,是因为cycle/ID/time现在在my.df中唯一地定义了一行。

票数 22
EN

Stack Overflow用户

发布于 2012-05-15 03:18:55

代码语言:javascript
复制
   reshape(my.df,
           idvar = "ID",
           timevar = "TIME",
           direction = "wide")

给出

代码语言:javascript
复制
  ID X.1 Y.1 X.2 Y.2 X.3 Y.3 X.4 Y.4 X.5 Y.5
1  A   1  16   4  19   7  22  10  25  13  28
2  B   2  17   5  20   8  23  11  26  14  29
3  C   3  18   6  21   9  24  12  27  15  30
票数 22
EN

Stack Overflow用户

发布于 2015-03-19 23:37:32

使用data.table_1.9.5,这可以在没有melt的情况下完成,因为它可以处理多个value.var列。您可以从here安装它

代码语言:javascript
复制
 library(data.table)
 dcast(setDT(my.df), ID~TIME, value.var=c('X', 'Y'))
 #   ID 1_X 2_X 3_X 4_X 5_X 1_Y 2_Y 3_Y 4_Y 5_Y
 #1:  A   1   4   7  10  13  16  19  22  25  28
 #2:  B   2   5   8  11  14  17  20  23  26  29
 #3:  C   3   6   9  12  15  18  21  24  27  30
票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10589693

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档