使用多个变量和一些时间不变将数据框从宽重塑为面板
Posted
技术标签:
【中文标题】使用多个变量和一些时间不变将数据框从宽重塑为面板【英文标题】:Reshape data frame from wide to panel with multiple variables and some time invariant 【发布时间】:2011-07-14 07:27:04 【问题描述】:这是数据分析中的一个基本问题,Stata 一步到位解决。
使用时不变数据 (x0) 和 2000 年和 2005 年的时变数据 (x1,x2) 创建一个宽数据框:
d1 <- data.frame(subject = c("id1", "id2"),
x0 = c("male", "female"),
x1_2000 = 1:2,
x1_2005 = 5:6,
x2_2000 = 1:2,
x2_2005 = 5:6
)
s.t.
subject x0 x1_2000 x1_2005 x2_2000 x2_2005
1 id1 male 1 5 1 5
2 id2 female 2 6 2 6
我想把它塑造成一个面板,所以数据看起来像这样:
subject x0 time x1 x2
1 id1 male 2000 1 1
2 id2 female 2000 2 2
3 id1 male 2005 5 5
4 id2 female 2005 6 6
我可以通过reshape
s.t. 做到这一点
d2 <-reshape(d1,
idvar="subject",
varying=list(c("x1_2000","x1_2005"),
c("x2_2000","x2_2005")),
v.names=c("x1","x2"),
times = c(2000,2005),
direction = "long",
sep= "_")
我主要担心的是,当您有几十个变量时,上述命令会变得很长。在stata
中,只需键入:
reshape long x1 x2, i(subject) j(year)
R中有这么简单的解决方案吗?
【问题讨论】:
【参考方案1】:reshape
可以猜出它的许多参数。在这种情况下,指定以下内容就足够了。不使用任何包。
reshape(d1, dir = "long", varying = 3:6, sep = "_")
给予:
subject x0 time x1 x2 id
1.2000 id1 male 2000 1 1 1
2.2000 id2 female 2000 2 2 2
1.2005 id1 male 2005 5 5 1
2.2005 id2 female 2005 6 6 2
【讨论】:
不错!但是,当变量被命名为 sample_1_2000 等时会发生什么......可以使用sep=
选项更具体化吗?
@Fred,使用split
参数代替sep
,即reshape(d1, dir = "long", varying = 3:6, split = list(regexp = "_2", include = TRUE))
,或将这种情况简化为问题中的情况,即reshape(setNames(d1, sub("sample_", "", names(d1))), dir = "long", varying = 3:6, sep = "_")
【参考方案2】:
这里是一个使用 reshape2 包的简短示例:
library(reshape2)
library(stringr)
# it is always useful to start with melt
d2 <- melt(d1, id=c("subject", "x0"))
# redefine the time and x1, x2, ... separately
d2 <- transform(d2, time = str_replace(variable, "^.*_", ""),
variable = str_replace(variable, "_.*$", ""))
# finally, cast as you want
d3 <- dcast(d2, subject+x0+time~variable)
现在您甚至不需要指定 x1 和 x2。 如果变量增加,此代码有效:
> d1 <- data.frame(subject = c("id1", "id2"), x0 = c("male", "female"),
+ x1_2000 = 1:2,
+ x1_2005 = 5:6,
+ x2_2000 = 1:2,
+ x2_2005 = 5:6,
+ x3_2000 = 1:2,
+ x3_2005 = 5:6,
+ x4_2000 = 1:2,
+ x4_2005 = 5:6
+ )
>
> d2 <- melt(d1, id=c("subject", "x0"))
> d2 <- transform(d2, time = str_replace(variable, "^.*_", ""),
+ variable = str_replace(variable, "_.*$", ""))
>
> d3 <- dcast(d2, subject+x0+time~variable)
>
> d3
subject x0 time x1 x2 x3 x4
1 id1 male 2000 1 1 1 1
2 id1 male 2005 5 5 5 5
3 id2 female 2000 2 2 2 2
4 id2 female 2005 6 6 6 6
【讨论】:
谢谢,这很有用。不太清楚transform
在做什么(帮助文件不是很有帮助),也不清楚如何解释"^.*_"
和"_.*$"
。我问是因为有些变量实际上被命名为“sample_1_2000”等......
也许这对于名为“sample_1_2000”的年份数据等更直观:temp1 <- transform(temp, time = str_sub(variable, -4), variable = str_sub(variable, 1,str_length(variable)-5))
@Fred 它取决于变量名的格式。如果(至少部分)字符的长度是固定的,那么你的方式会更容易。否则,正则表达式更灵活。以上是关于使用多个变量和一些时间不变将数据框从宽重塑为面板的主要内容,如果未能解决你的问题,请参考以下文章