【问题标题】: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中有这么简单的解决方案吗?

【问题讨论】:

    标签: r panel stata reshape data-manipulation


    【解决方案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 &lt;- transform(temp, time = str_sub(variable, -4), variable = str_sub(variable, 1,str_length(variable)-5))
    • @Fred 它取决于变量名的格式。如果(至少部分)字符的长度是固定的,那么你的方式会更容易。否则,正则表达式更灵活。
    猜你喜欢
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 2020-07-12
    • 2017-10-13
    • 1970-01-01
    相关资源
    最近更新 更多