【问题标题】:Fastest way to reshape variable values as columns将变量值重塑为列的最快​​方法
【发布时间】:2011-12-29 20:11:45
【问题描述】:

我有一个大约 300 万行的数据集,结构如下:

PatientID| Year | PrimaryConditionGroup
---------------------------------------
1        | Y1   | TRAUMA
1        | Y1   | PREGNANCY
2        | Y2   | SEIZURE
3        | Y1   | TRAUMA

作为 R 的新手,我很难找到正确的方法将数据重塑为下面概述的结构:

PatientID| Year | TRAUMA | PREGNANCY | SEIZURE
----------------------------------------------
1        | Y1   | 1      | 1         | 0
2        | Y2   | 0      | 0         | 1
3        | Y1   | 1      | 0         | 1

我的问题是:创建 data.frame 的最快/最优雅的方法是什么,其中 PrimaryConditionGroup 的值成为列,按 PatientID 和 Year 分组(计算出现次数)?

【问题讨论】:

    标签: r performance reshape


    【解决方案1】:

    可能有更简洁的方法可以做到这一点,但就速度而言,很难击败基于data.table 的解决方案:

    df <- read.table(text="PatientID Year  PrimaryConditionGroup
    1         Y1    TRAUMA
    1         Y1    PREGNANCY
    2         Y2    SEIZURE
    3         Y1    TRAUMA", header=T)
    
    library(data.table)
    dt <- data.table(df, key=c("PatientID", "Year"))
    
    dt[ , list(TRAUMA =    sum(PrimaryConditionGroup=="TRAUMA"),
               PREGNANCY = sum(PrimaryConditionGroup=="PREGNANCY"),
               SEIZURE =   sum(PrimaryConditionGroup=="SEIZURE")),
       by = list(PatientID, Year)]
    
    #      PatientID Year TRAUMA PREGNANCY SEIZURE
    # [1,]         1   Y1      1         1       0
    # [2,]         2   Y2      0         0       1
    # [3,]         3   Y1      1         0       0
    

    编辑:aggregate() 提供了一个“基本 R”解决方案,它可能更惯用也可能不会更惯用。 (唯一的复杂之处是聚合返回一个矩阵,而不是一个 data.frame;下面的第二行解决了这个问题。)

    out <- aggregate(PrimaryConditionGroup ~ PatientID + Year, data=df, FUN=table)
    out <- cbind(out[1:2], data.frame(out[3][[1]]))
    

    第二次编辑最后,使用reshape 包的简洁解决方案将您带到同一个地方。

    library(reshape)
    mdf <- melt(df, id=c("PatientID", "Year"))
    cast(PatientID + Year ~ value, data=j, fun.aggregate=length)
    

    【讨论】:

    • +1 ddply 不会少打字,真的,当然会慢得多。
    • 你为什么会考虑 ddply 来解决这个问题?
    • 嗨乔希,谢谢你,这按预期工作并且表现良好。重塑数据的最简洁/惯用的方法是什么(如果性能不是问题)
    • 嗨,马特——我刚刚汇总了一个替代解决方案,并将其添加到帖子中。这看起来更简洁/惯用吗?
    • 有没有办法在 MS SQL 表中做到这一点
    【解决方案2】:

    在 C 中实现了快速的 meltdcast data.table 特定方法,版本为 &gt;=1.9.0。这是与@Josh 发布的关于 300 万行数据的其他出色答案的比较(不包括 base:::aggregate,因为它需要相当长的时间)。

    有关新闻条目的更多信息,请转到here

    我假设您有 1000 名患者,总共 5 年。您可以相应地调整变量patientsyear

    require(data.table) ## >= 1.9.0
    require(reshape2)
    
    set.seed(1L)
    patients = 1000L
    year = 5L
    n = 3e6L
    condn = c("TRAUMA", "PREGNANCY", "SEIZURE")
    
    # dummy data
    DT <- data.table(PatientID = sample(patients, n, TRUE),
                     Year = sample(year, n, TRUE), 
                     PrimaryConditionGroup = sample(condn, n, TRUE))
    
    DT_dcast <- function(DT) {
        dcast.data.table(DT, PatientID ~ Year, fun.aggregate=length)
    }
    
    reshape2_dcast <- function(DT) {
        reshape2:::dcast(DT, PatientID ~ Year, fun.aggregate=length)
    }
    
    DT_raw <- function(DT) {
        DT[ , list(TRAUMA = sum(PrimaryConditionGroup=="TRAUMA"),
                PREGNANCY = sum(PrimaryConditionGroup=="PREGNANCY"),
                  SEIZURE = sum(PrimaryConditionGroup=="SEIZURE")),
        by = list(PatientID, Year)]
    }
    
    # system.time(.) timed 3 times
    #         Method Time_rep1 Time_rep2 Time_rep3
    #       dcast_DT     0.393     0.399     0.396
    #    reshape2_DT     3.784     3.457     3.605
    #         DT_raw     0.647     0.680     0.657
    

    dcast.data.table 比使用 data.table 的普通聚合快约 1.6 倍,比 reshape2:::dcast 快 8.8 倍。

    【讨论】:

      猜你喜欢
      • 2011-10-17
      • 1970-01-01
      • 2012-08-08
      • 2017-12-07
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多