【问题标题】:r reshape data long to wide with unknown number of columnsr 用未知的列数将数据从长到宽重塑
【发布时间】:2012-07-03 08:17:56
【问题描述】:

我确信这是微不足道的,但我不知道怎么做。

我有一个数据框,其中有个人,每个人都可以有多个属性,并且每个属性都以多种方式分类。目前它是长形的,有一张唱片看起来像(在示意图中,实际上它有点复杂):

IndividualID Property PropClass 
1            X         A 
1            Y         B 
2            X         A 
3            Y         B
3            W         C
3            Z         A

我想要的是每个单独的 ID 有一行,带有单独的 ID,然后是该个人在原始文件中的每个属性和 PropClass 的列对,所以在这种情况下:

 IndividualID  Prop1   PropClass1 Prop2  PropClass2  Prop3  PropClass3
 1             X       A          Y      B           NA     NA
 2             X       A          NA     NA          NA     NA
 3             Y       B          W      C           Z      A

因此,Prop 和 PropClass 变量的数量必须与原始数据集中任何个人 ID 的最大行数一样多(不大,大约 5),并且个人在原始数据集中的行数少于原始数据集中的行数那个最大数量,对那个人没有任何意义的额外列中有 NA。个人的 Prop 和 PropClass 变量的顺序无关紧要(尽管它也可能是长格式文件上的原始顺序)。

显然,如果您有一对 Prop 和 propClass 列用于 Prop 的每个可能值,那么很容易做到这一点(例如,使用 reshape),但是 Prop 有数百个可能值,因此文件变得庞大且无用。我不敢相信没有一种简单的方法可以做我想做的事,但是尽管在我看来是刻苦的搜索,但我还是没有找到它。请告诉我我是个白痴,如果是的话,我该如何治愈我的白痴。

【问题讨论】:

    标签: r reshape


    【解决方案1】:

    可能有一种更有效的方法可以做到这一点,但我现在想不出。对于需要转换为宽格式的两个变量,我认为您可能需要将它们分别转换,然后将两者合并在一起。我很想被证明是错误的。为此,我创建了两个新变量,它们为每个新 ID 生成列序列。这将允许他们轻松地填充 NA。使用新列,很容易将它们转换为正确的格式并将它们合并在一起。

    library(plyr)
    library(reshape2)
    
    #Assumes your data is read into a variable named x
    x <- ddply(x, "IndividualID", transform, 
          castPropClass = paste0("PropClass", seq(length(PropClass))),
          castProp = paste0("Prop", seq(length(Property))))
    
    #Use these two new variables to cast into wide format. Wrap in merge to join together:
    merge(dcast(IndividualID ~ castPropClass, value.var = "PropClass", data = x),
          dcast(IndividualID ~ castProp,      value.var = "Property",  data = x))
    #Gives you this:
      IndividualID PropClass1 PropClass2 PropClass3 Prop1 Prop2 Prop3
    1            1          A          B       <NA>     X     Y  <NA>
    2            2          A       <NA>       <NA>     X  <NA>  <NA>
    3            3          B          C          A     Y     W     Z
    

    这显然没有正确的列“顺序”,但数据本身是正确的。

    【讨论】:

    • 谢谢,这行得通(并且相当容易扩展到我真正遇到的稍微复杂的情况)。
    【解决方案2】:

    这样的事情可以接受吗?

    test.dt<-data.frame(id=(c(1,1,2,3,3,3)), property=(c("X","Y","X","Y","W","Z")), property.clss=(c("A","B","A","B","C","A")))
    library(reshape)
    m<-melt(data=test.dt, id.vars="id", measure.vars=c("property.clss"))
    m
    n<-melt(data=test.dt, id.vars="id", measure.vars=c("property"))
    n
    c1<-data.frame(cast(m, id~value))
    colnames(c1)<-c("id", paste("property",colnames(c1)[colnames(c1)!="id"],sep=""))
    c1
    c2<-data.frame(cast(n,id~value))
    colnames(c2)<-c("id", paste("property.clss",(colnames(c2)[colnames(c2)!="id"]),sep=""))
    c2
    merge(c1,c2,by="id")
    

    【讨论】:

    • 这基本上是我所概述的,只是在一组不同的步骤中......很高兴看到我们或多或少在同一页面上。
    • 嗨@Chase。我想我们实际上是同时提交的!我觉得你的答案更干净更漂亮。
    • 是的,谢谢,我很确定这也适用于我,但我选择了 @Chase 的版本,因为它更简洁。
    猜你喜欢
    • 1970-01-01
    • 2019-11-22
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    相关资源
    最近更新 更多