Разделение строкового столбца на множество с использованием tidyverse - PullRequest
0 голосов
/ 12 января 2019

У меня есть строковый столбец с запятыми. Я хочу преобразовать этот столбец в несколько помеченных столбцов, значения которых будут заполнены соответствующим образом. Кадр выходных данных будет иметь 3 столбца (A, B и C). В строке 1 столбцы A и B будут заполнены "Да", а C - "Нет". В строке 2 все 3 столбца будут заполнены "Да" и т. Д.

df1 <- data.frame(X= c("A, B", "A, B, C", "A", "A, C"))

df1
        X
1    A, B
2 A, B, C
3       A
4    A, C

Требуемый выход

A    B    C
Yes  Yes  No
Yes  Yes  Yes
Yes  No   No
Yes  No   Yes

Любой намек, пожалуйста.

Ответы [ 6 ]

0 голосов
/ 12 января 2019

Через stringi

stringi::stri_split_fixed(df1$X, ", ", simplify = TRUE) != ""
#      [,1]  [,2]  [,3]
# [1,] TRUE  TRUE FALSE
# [2,] TRUE  TRUE  TRUE
# [3,] TRUE FALSE FALSE
# [4,] TRUE  TRUE FALSE

TRUE / FALSE по существу yes / no, но если вам нужна матрица символов, вы всегда можете сделать ifelse(., "yes", "no") и сохранить структуру матрицы.

0 голосов
/ 12 января 2019

Здесь можно использовать base R с table. Мы разбиваем столбец 'X' на , на list из vector с, преобразуем его в два столбца data.frame с stack, получаем частоту с table и преобразуем в логическую

table(stack(setNames(strsplit(as.character(df1$X), ", +"), 
                    seq_len(nrow(df1))))[2:1]) > 0
 #   values
#ind    A     B     C
#  1 TRUE  TRUE FALSE
#  2 TRUE  TRUE  TRUE
#  3 TRUE FALSE FALSE
#  4 TRUE FALSE  TRUE
0 голосов
/ 12 января 2019

Вот еще одно решение в base

lets <- strsplit(as.character(.subset2(df1,1L)), ', ')
lets_unique <- unique(unlist(lets))
vapply(seq_along(lets_unique),function(k)grepl(lets_unique[k],lets),logical(length(lets)))
#      [,1]  [,2]  [,3]
# [1,] TRUE  TRUE FALSE
# [2,] TRUE  TRUE  TRUE
# [3,] TRUE FALSE FALSE
# [4,] TRUE FALSE  TRUE
0 голосов
/ 12 января 2019

Использование splitstackshape

library(splitstackshape)
newdf=cSplit_e(df1, "X", sep = ", ",type = "character")
newdf[newdf==1]='Yes'
newdf[is.na(newdf)]='No'

newdf
        X X_A X_B X_C
1    A, B Yes Yes  No
2 A, B, C Yes Yes Yes
3       A Yes  No  No
4    A, C Yes  No Yes
0 голосов
/ 12 января 2019

Немного другой подход, который не зависит от группировки. Окончательное преобразование в «Да /« Нет »также выполняется по столбцам, а не полагается на преобразование длинных данных в широкие. Для очень большого набора данных это может быть несколько более эффективным.

df2 <- df1 %>% 
  mutate(row_num = 1:n()) %>% 
  separate_rows(X) %>% 
  spread(X, 1) %>% 
  select(-row_num) %>% 
  mutate_all(~ifelse(!is.na(.), 'Yes', 'No'))

    A   B   C
1 Yes Yes  No
2 Yes Yes Yes
3 Yes  No  No
4 Yes  No Yes
0 голосов
/ 12 января 2019

Примерно так:

library(tidyverse)

df1 %>%
  mutate(id = row_number()) %>% 
  separate_rows(X) %>% 
  group_by(id) %>% 
  mutate(Y = "yes") %>% 
  spread(X, Y, fill = "no")

# A tibble: 4 x 4
# Groups:   id [4]
     id A     B     C    
  <int> <chr> <chr> <chr>
1     1 yes   yes   no   
2     2 yes   yes   yes  
3     3 yes   no    no   
4     4 yes   no    yes  
...