【问题标题】:Collapse only some variables long to wide format in R在R中仅折叠一些长到宽格式的变量
【发布时间】:2018-02-14 08:51:55
【问题描述】:

我对 R 比较陌生,每次需要“重塑”数据时,我都感到非常困惑。我的数据如下所示:

有:

  ID ever_smoked alcoholic        medication dosage
1  1          no        no humira/adalimumab   40mg
2  1          no        no        prednisone   15mg
3  1          no        no      azathioprine   30mg
4  1          no        no            rowasa    9mg
5  2         yes        no            lialda   20mg
6  2         yes        no    mercaptopurine     1g
7  2         yes        no            asacol 1600mg

想要:

 ID  ever_smoked  alcoholic  medication
1  1          no        no   humira/adalimumab, prednisone, azathioprine, rowasa
2  2         yes        no   lialda, mercaptopurine, asacol

  dosage                  most_recent_med     most_recent_dose
1 40mg, 15mg, 30mg, 9mg   rowasa              9mg
2 20mg, 1g, 1600mg        asacol              1600mg

(请注意,它应该是 2 个观察值和 7 个变量)。

本质上,我想 (1) 只折叠几个变量,(2) 保留其他变量的第一行,并且 (3) 根据一些变量的最后条目创建 2 个新变量变量。

重现代码:

have <- data.frame(ID = c(1, 1, 1, 1, 2, 2, 2),
    ever_smoked = c("no", "no", "no", "no", "yes", "yes", "yes"), 
    alcoholic = c("no", "no", "no", "no", "no", "no", "no"),
    medication = c("humira/adalimumab", "prednisone", "azathioprine", "rowasa", "lialda", "mercaptopurine", "asacol"),
    dosage = c("40mg", "15mg", "30mg", "9mg", "20mg", "1g", "1600mg"), stringsAsFactors = FALSE)

want <- data.frame(ID = c(1, 2),
    ever_smoked = c("no", "yes"), 
    alcoholic = c("no", "no"),
    medication = c("humira/adalimumab, prednisone, azathioprine, rowasa", "lialda, mercaptopurine, asacol"),
    dosage = c("40mg, 15mg, 30mg, 9mg", "20mg, 1g, 1600mg"),
    most_recent_med = c("rowasa", "asacol"),
    most_recent_dose = c("9mg", "1600mg"), stringsAsFactors = FALSE)

谢谢。

【问题讨论】:

    标签: r dataframe dplyr reshape collapse


    【解决方案1】:

    这里有一些不同的方法:

    1) sqldf

    library(sqldf)
    sqldf("select ID, 
                  ever_smoked, 
                  alcoholic, 
                  group_concat(medication) as medication,
                  group_concat(dosage) as dosage, 
                  medication as last_medication, 
                  dosage as last_doage
            from have
            group by ID")
    

    给予:

      ID ever_smoked alcoholic                                       medication             dosage last_medication last_doage
    1  1          no        no humira/adalimumab,prednisone,azathioprine,rowasa 40mg,15mg,30mg,9mg          rowasa        9mg
    2  2         yes        no                     lialda,mercaptopurine,asacol     20mg,1g,1600mg          asacol     1600mg
    

    2) 数据表

    library(data.table)
    have_dt <- data.table(have)
    have_dt[, list(medication = toString(medication),
                   dosage = toString(dosage),
                   last_medication = medication[.N],
                   last_dosage = dosage[.N]),
               by = "ID,ever_smoked,alcoholic"]
    

    给予:

       ID ever_smoked alcoholic                                          medication                dosage last_medication last_dosage
    1:  1          no        no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg          rowasa         9mg
    2:  2         yes        no                      lialda, mercaptopurine, asacol      20mg, 1g, 1600mg          asacol      1600mg
    

    3) 基地 - 由

    do.call("rbind", by(have, have$ID, with, data.frame(
         ID = ID[1], 
         ever_smoked = ever_smoked[1], 
         alcoholic = alcoholic[1],
         medication = toString(medication),
         dosage = toString(dosage),
         last_medication = tail(medication, 1),
         last_dosage = tail(dosage, 1))))
    

    给予:

      ID ever_smoked alcoholic                                          medication                dosage last_medication last_dosage
    1  1          no        no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg          rowasa         9mg
    2  2         yes        no                      lialda, mercaptopurine, asacol      20mg, 1g, 1600mg          asacol      1600mg
    

    请注意,这也可以写成:

    do.call("rbind", by(have, have$ID, function(x) with(x, data.frame(
         ID = ID[1], 
         ever_smoked = ever_smoked[1], 
         alcoholic = alcoholic[1],
         medication = toString(medication),
         dosage = toString(dosage),
         last_medication = tail(medication, 1),
         last_dosage = tail(dosage, 1)))))
    

    4) 基数 - 聚合

    aggregate(. ~ ID + ever_smoked + alcoholic, have,
      function(x) c(values = toString(x), last = as.character(tail(x, 1))))
    

    给予:

      ID ever_smoked alcoholic                                   medication.values medication.last         dosage.values dosage.last
    1  1          no        no humira/adalimumab, prednisone, azathioprine, rowasa          rowasa 40mg, 15mg, 30mg, 9mg         9mg
    2  2         yes        no                      lialda, mercaptopurine, asacol          asacol      20mg, 1g, 1600mg      1600mg
    

    请注意,这会返回一个 2 x 5 的数据框,其中最后两列各是 2 列矩阵,这比展平形式更便于索引,但如果首选展平则:do.call("data.frame", DF)

    【讨论】:

      【解决方案2】:

      这是一个汇总过程,你可以使用summarise_all并传递两个函数来汇总每一列:一个用toString折叠列,一个用last取最后一行:

      have %>% 
          group_by(ID, ever_smoked, alcoholic) %>% 
          summarise_all(funs(toString(.), most_recent = last(.)))
      
      # A tibble: 2 x 7
      # Groups:   ID, ever_smoked [?]
      #     ID ever_smoked alcoholic                                 medication_toString       dosage_toString medication_most_recent dosage_most_recent
      #  <dbl>       <chr>     <chr>                                               <chr>                 <chr>                  <chr>              <chr>
      #1     1          no        no humira/adalimumab, prednisone, azathioprine, rowasa 40mg, 15mg, 30mg, 9mg                 rowasa                9mg
      #2     2         yes        no                      lialda, mercaptopurine, asacol      20mg, 1g, 1600mg                 asacol             1600mg
      

      假设 ever_smoked酒精 对于此处的每个 ID 都是唯一的。

      【讨论】:

        猜你喜欢
        • 2021-10-23
        • 2015-10-14
        • 1970-01-01
        • 2021-12-24
        • 2016-06-07
        • 2021-04-15
        • 1970-01-01
        • 2019-03-14
        • 1970-01-01
        相关资源
        最近更新 更多