Как создать двоичные переменные для нескольких пользователей в определенной ячейке?

#r #dataframe

#r #фрейм данных

Вопрос:

Я имею дело с немного шатким фреймом данных. Я работаю со стандартным табличным набором данных / .csv-файлом, который по большей части является довольно стандартным, однако в одном столбце каждое наблюдение представляет собой список пользователей. Вот как это выглядит:

 Layer       Grade              Players
Top           A         NY 08; NY 27; NY 80
Bottom        D         MA 27; MA 45; MA 65
Middle        B         NY 09; MA 48; NY 66
...
  

Как вы можете видеть, фрейм данных является стандартным, за исключением столбца Players . Как я мог бы добавить столбец для каждого игрока, который предоставляет двоичный индикатор того, были ли они в игре или нет? Я бы хотел, чтобы приведенный выше фрейм данных стал таким:

 Layer       Grade       Players                       NYAL 08     NYAL 27     NYAL 80    MAAC 27
Top           A         NYAL 08; NYAL 27; NYAL 80       1           1           1          0
Bottom        D         MAAC 27; MAAC 45; MAAC 65       0           0           0          1
Middle        B         NYAL 08; MAAC 48; NYAL 66       1           0           0          0
...
  

И так далее.

Спасибо!

Ответ №1:

Мы можем использовать cSplit_e from splitstackshape . Это позволило бы получить вывод компактным способом в одной строке

 library(splitstackshape)
out <- cSplit_e(df1, 'Players', sep=";", type = "character", fill = 0)
out
  

-вывод

 #Layer Grade             Players Players_MA 27 Players_MA 45 Players_MA 48 Players_MA 65 Players_NY 08 Players_NY 09 Players_NY 27
#1    Top     A NY 08; NY 27; NY 80             0             0             0             0             1             0             1
#2 Bottom     D MA 27; MA 45; MA 65             1             1             0             1             0             0             0
#3 Middle     B NY 09; MA 48; NY 66             0             0             1             0             0             1             0
#  Players_NY 66 Players_NY 80
#1             0             1
#2             0             0
#3             1             0
  

Если мы хотим удалить префикс в именах столбцов

 names(out)[-(1:3)] <- sub('Players_', '', names(out)[-(1:3)])
  

Или другой вариант mtabulate

 cbind(df1, mtabulate(strsplit(df1$Player, ";\s ")))
  

-вывод

 #   Layer Grade             Players MA 27 MA 45 MA 48 MA 65 NY 08 NY 09 NY 27 NY 66 NY 80
#1    Top     A NY 08; NY 27; NY 80     0     0     0     0     1     0     1     0     1
#2 Bottom     D MA 27; MA 45; MA 65     1     1     0     1     0     0     0     0     0
#3 Middle     B NY 09; MA 48; NY 66     0     0     1     0     0     1     0     1     0
  

данные

 df1 <- structure(list(Layer = c("Top", "Bottom", "Middle"), Grade = c("A", 
"D", "B"), Players = c("NY 08; NY 27; NY 80", "MA 27; MA 45; MA 65", 
"NY 09; MA 48; NY 66")), class = "data.frame", row.names = c(NA, 
-3L))
  

Комментарии:

1. Я попробовал подход ‘splitstackshape’, но я получаю эту ошибку: ‘Ошибка в rep (seq.int (len), vapply(listOfValues, length, integer(1L))) : недопустимый аргумент ‘times» Есть мысли?

2. @rogues77 ошибка основана на тех же данных, которые я показал в своем сообщении или в другом сообщении

3. @rogues77 вы также можете попробовать этот mtabulate подход

4. Ах! Вы правы, я изменил свой код перед запуском вашего решения, и это меня испортило. Моя ошибка. Еще одна вещь — есть ли какой-либо способ удалить «Players_» из новых имен столбцов, не удаляя начальный столбец «игроки»?

5. На самом деле я использовал функцию mtabulate, которая работает отлично. Большое вам спасибо!

Ответ №2:

Попробуйте этот tidyverse подход с separate_rows() помощью and pivot_wider() , который даст результат, близкий к тому, который вы хотите:

 library(tidyverse)
#Code
df2 <- df %>% mutate(Dup=Players) %>%
  separate_rows(Dup,sep = '; ') %>%
  mutate(id=1) %>%
  pivot_wider(names_from = Dup,values_from=id) %>%
  replace(is.na(.),0)
  

Вывод:

 # A tibble: 3 x 12
  Layer  Grade Players   `NY 08` `NY 27` `NY 80` `MA 27` `MA 45` `MA 65` `NY 09` `MA 48` `NY 66`
  <chr>  <chr> <chr>       <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1 Top    A     NY 08; N~       1       1       1       0       0       0       0       0       0
2 Bottom D     MA 27; M~       0       0       0       1       1       1       0       0       0
3 Middle B     NY 09; M~       0       0       0       0       0       0       1       1       1
  

Некоторые используемые данные:

 #Data
df <- structure(list(Layer = c("Top", "Bottom", "Middle"), Grade = c("A", 
"D", "B"), Players = c("NY 08; NY 27; NY 80", "MA 27; MA 45; MA 65", 
"NY 09; MA 48; NY 66")), class = "data.frame", row.names = c(NA, 
-3L))