代码之家  ›  专栏  ›  技术社区  ›  Roccer

按id从宽到长收集列[重复]

  •  2
  • Roccer  · 技术社区  · 6 年前

    set.seed(100)
    
    drugs <- data.frame(id = 1:5, 
                    drug_1 = letters[1:5], drug_dos_1 = sample(100,5),
                    drug_2 = letters[3:7], drug_dos_2 = sample(100,5)
    )
    
    id drug_1 drug_dos_1 drug_2 drug_dos_2
    1      a         31      c         49
    2      b         26      d         81
    3      c         55      e         37
    4      d          6      f         54
    5      e         45      g         17
    

    我想把这张乱七八糟的桌子改成一张整洁的桌子,一列有一个id的所有药品,一列有相应的药品剂量。桌子最后应该是这样的:

    id drug dosage
    1  a    31
    1  c    49
    2  b    26
    2  d    81
    etc
    

    我想这可以通过使用一个重塑函数来实现,这个函数可以将数据从宽格式转换为长格式,但我没有做到。

    2 回复  |  直到 6 年前
        1
  •  3
  •   akrun    6 年前

    一种选择是 melt data.table 可能需要多次 patterns measure 论点

    library(data.table)
    melt(setDT(drugs), measure = patterns('^drug_\\d+$', 'dos'),
         value.name = c('drug', 'dosage'))[, variable := NULL][order(id)]
    #   id drug dosage
    #1:  1    a     31
    #2:  1    c     49
    #3:  2    b     26
    #4:  2    d     81
    #5:  3    c     55
    #6:  3    e     37
    #7:  4    d      6
    #8:  4    f     54
    #9:  5    e     45
    #10  5    g     17
    

    在这里,“药物”在所有列中都很常见,所以我们需要创建一个独特的模式。一种方法是指定起始位置( ^ _ )一个或多个数字( \\d+ )最后( $

        2
  •  2
  •   A. Suliman    6 年前
    library(dplyr)
    drugs %>% gather(key,val,-id) %>% mutate(key=gsub('_\\d','',key)) %>% #replace _1 and _2 at the end wiht nothing
              mutate(key=gsub('drug_','',key)) %>% group_by(key) %>%  #replace drug_ at the start of dos with nothin and gruop by key
              mutate(row=row_number()) %>% spread(key,val) %>%
              select(id,drug,dos,-row)
    
    
     # A tibble: 10 x 3
      id drug  dos  
      <int> <chr> <chr>
      1     1 a     31   
      2     1 c     49   
      3     2 b     26   
      4     2 d     81   
      5     3 c     55   
      6     3 e     37   
      7     4 d     6    
      8     4 f     54   
      9     5 e     45   
     10     5 g     17   
      Warning message:
      attributes are not identical across measure variables;
      they will be dropped
    #This warning generated as we merged drug(chr) and dose(num) into one column (val)