将行值拆分为列

split row values into columns

我有一些数据如下所示:

samp
# A tibble: 5 x 2
     ID Source        
  <dbl> <chr>         
1 34221 75            
2 33861 75            
3 59741 126,123       
4 56561 111,105       
5 55836 36,34,34,36,22

对于任何不同的值,我想创建一个新列。如果该值连续存在,我想估算一个 "x" 否则不应估算任何值。

预期结果示例(伪代码):

ID      75  126 123 111 105 36 34 22         
1 34221 x            
2 33861 x            
3 59741     x   x       
4 56561             x   x    
5 55836                     x  x  x

我通过tydr包的separtate函数试了一下。像这样开始。

into = unique(unlist(strsplit(samp$Source, ",")))

samp %>% separate(col = "Source", into = into, sep = ",")

但是,这不起作用,因为如果一行中有多个值,则这些值将不会分配给相应的列(例如,对于 ID 59741,值 126 在第 75 列中,而不是在列 126)。

 A tibble: 5 x 9
     ID `75`  `126` `123` `111` `105` `36`  `34`  `22` 
  <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 34221 75    NA    NA    NA    NA    NA    NA    NA   
2 33861 75    NA    NA    NA    NA    NA    NA    NA   
3 59741 126   123   NA    NA    NA    NA    NA    NA   
4 56561 111   105   NA    NA    NA    NA    NA    NA   
5 55836 36    34    34    36    22    NA    NA    NA  

这是一个dput:

structure(list(ID = c(34221, 33861, 59741, 56561, 55836), Source = c("75", 
"75", "126,123", "111,105", "36,34,34,36,22")), row.names = c(NA, 
-5L), class = c("tbl_df", "tbl", "data.frame"))

splitstackshape对于此类操作非常方便,即

library(splitstackshape)

cSplit_e(df, "Source", mode = "binary", type = "character", fill = 0, drop = TRUE)

这给出了,

     ID Source_105 Source_111 Source_123 Source_126 Source_22 Source_34 Source_36 Source_75
1 34221          0          0          0          0         0         0         0         1
2 33861          0          0          0          0         0         0         0         1
3 59741          0          0          1          1         0         0         0         0
4 56561          1          1          0          0         0         0         0         0
5 55836          0          0          0          0         1         1         1         0

还可以:

library(tidyverse)

df %>%
  mutate(Source = strsplit(Source, ","),
         dummy = "x") %>% 
  unnest() %>% distinct() %>%
  spread(Source, dummy)

输出:

     ID `105` `111` `123` `126` `22`  `34`  `36`  `75` 
  <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 33861 NA    NA    NA    NA    NA    NA    NA    x    
2 34221 NA    NA    NA    NA    NA    NA    NA    x    
3 55836 NA    NA    NA    NA    x     x     x     NA   
4 56561 x     x     NA    NA    NA    NA    NA    NA   
5 59741 NA    NA    x     x     NA    NA    NA    NA   

另一种选择是使用 tidyr::separate_rows

library(dplyr)
library(tidyr)
df %>% separate_rows(Source,sep=',') %>% distinct() %>% 
       mutate(dummy='X') %>% spread(Source,dummy)

     ID  105  111  123  126   22   34   36   75
1 33861 <NA> <NA> <NA> <NA> <NA> <NA> <NA>    X
2 34221 <NA> <NA> <NA> <NA> <NA> <NA> <NA>    X
3 55836 <NA> <NA> <NA> <NA>    X    X    X <NA>
4 56561    X    X <NA> <NA> <NA> <NA> <NA> <NA>
5 59741 <NA> <NA>    X    X <NA> <NA> <NA> <NA>