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

Я пытаюсь создать несколько фиктивных переменных, основываясь на одном столбце под названием "Теги" в моем df (2 строки, 2 столбца, Tags а также Score, Проблема в том, что в каждой ячейке столбца Tags может быть любое количество значений chr (до 30 значений). Я хочу создать новую фиктивную переменную для каждого уникального значения chr в одной ячейке. Это должно сказать мне, имеет ли дело конкретное значение или нет (1/0). Чтобы показать вам проблему, я включаю dput(df):

structure(list(Tags = structure(c(27L, 16L, 4L), .Label = c("\"aan het water\", \"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"er even tussenuit\", \"gebruik streekproducten\", \"iens topper 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", frans, glutenvrij, romantisch, wijnbar, zakelijk", 
"\"aan het water\", \"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"gebruik streekproducten\", \"iens topper 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", glutenvrij, kindvriendelijk, romantisch, wereldkeuken, zakelijk", 
"\"aan het water\", \"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", frans, glutenvrij, romantisch, zakelijk", 
"\"aan het water\", \"biologische gerechten\", \"gebruik streekproducten\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", frans, glutenvrij, romantisch, wijnbar, zakelijk", 
"\"aan het water\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"er even tussenuit\", \"iens topper 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", glutenvrij, grieks, romantisch", 
"\"aan het water\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", italiaans, kindvriendelijk, romantisch, zakelijk", 
"\"aan het water\", \"high tea\", brasserie, frans, kindvriendelijk, romantisch, zakelijk", 
"\"aan het water\", \"high tea\", kindvriendelijk, romantisch, wereldkeuken", 
"\"aan het water\", \"iens topper 2016\", italiaans, kindvriendelijk, romantisch, zakelijk", 
"\"aan het water\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", glutenvrij, kindvriendelijk, romantisch, wereldkeuken, zakelijk", 
"\"aan het water\", \"lactose intolerantie\", frans, glutenvrij, zakelijk", 
"\"aan het water\", frans", "\"all you can eat buffet\", \"er even tussenuit\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", glutenvrij, kindvriendelijk, romantisch, wereldkeuken, zakelijk", 
"\"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"er even tussenuit\", \"gebruik streekproducten\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", glutenvrij, kindvriendelijk, romantisch, wereldkeuken", 
"\"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"gebruik streekproducten\", \"high tea\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", frans, glutenvrij, kindvriendelijk, romantisch, zakelijk", 
"\"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"gebruik streekproducten\", \"iens topper 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", glutenvrij, kindvriendelijk, romantisch, zakelijk", 
"\"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"gebruik streekproducten\", \"lactose intolerantie\", \"met familie\", \"met vrienden\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", chinees, gastronomisch, glutenvrij, kindvriendelijk, romantisch, traditioneel, trendy, verjaardag, zakelijk", 
"\"biologische gerechten\", \"certificaat van uitmuntendheid tripadvisor 2016\", \"vegetarische gerechten\", italiaans, kindvriendelijk", 
"\"biologische gerechten\", \"gebruik streekproducten\", \"iens topper 2016\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", bbq/grill, glutenvrij, kindvriendelijk, romantisch, wijnbar", 
"\"biologische gerechten\", \"gebruik streekproducten\", \"lactose intolerantie\", \"vegetarische gerechten\", glutenvrij, romantisch, wereldkeuken", 
"\"biologische gerechten\", \"gebruik streekproducten\", frans, romantisch", 
"\"certificaat van uitmuntendheid tripadvisor 2016\", \"high tea\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", glutenvrij, romantisch, wereldkeuken, zakelijk", 
"\"er even tussenuit\", \"met familie\", \"met vrienden\", amerikaans, romantisch, trendy, verjaardag, wijnbar, zakelijk", 
"\"gebruik streekproducten\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", \"vegetarische gerechten\", frans, glutenvrij, romantisch, zakelijk", 
"\"high tea\", \"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", frans, glutenvrij, romantisch, zakelijk", 
"\"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", frans, glutenvrij, kindvriendelijk, romantisch, wijnbar, zakelijk", 
"\"lactose intolerantie\", \"noten allergie\", \"pinda allergie\", glutenvrij, kindvriendelijk, spaans", 
"\"lactose intolerantie\", frans, glutenvrij, romantisch, zakelijk", "grieks", "spaans"), class = "factor"), Score = c(8, 9, 8.8)), row.names = c(NA, 
-3L), class = c("tbl_df", "tbl", "data.frame"), .Names = c("Tags", 
"Score")) 

а также df$Tags[1] возвращает меня:

[1] "lactose intolerantie", "noten allergie", "pinda allergie", glutenvrij, kindvriendelijk, spaans
30 Levels: "aan het water", "biologische gerechten", "certificaat van uitmuntendheid tripadvisor 2016", "er even tussenuit", "gebruik streekproducten", "iens topper 2016", "lactose intolerantie", "noten allergie", "pinda allergie", "vegetarische gerechten", frans, glutenvrij, romantisch, wijnbar, zakelijk ...  

Вручную я могу запустить, например, следующее, и это работает:

df = mutate(df, lactose_intolerantie = ifelse(grepl("lactose intolerantie", Tags), 1, 0))

Он создал новый столбец, содержащий 1, когда значение "непереносимость лактозы" присутствовало, и ноль, когда оно отсутствует.

Я ищу способ сделать это быстрее, для каждого возможного значения chr. Надеюсь, кто-то может помочь. Большое спасибо за мысль.

2 ответа

Решение

Просто начальный шаг:

x1 = gsub("\"", "",unlist(strsplit(as.character(df$Tags[1]),",")))
x2 = gsub("\"", "",unlist(strsplit(as.character(df$Tags[2]),",")))
x3 = gsub("\"", "",unlist(strsplit(as.character(df$Tags[3]),",")))

# removing only spaces occuring at the start
x11=gsub("^ ","" ,x1)
x22=gsub("^ ","" ,x2)
x33=gsub("^ ","" ,x3)

# get the unique ones
x = unique(c(x11,x22,x33))

df1 = as.data.frame(lapply(as.list(x), function(x) as.numeric(grepl(x, df$Tags))))
colnames(df1) = x

> df1
  lactose intolerantie noten allergie pinda allergie glutenvrij kindvriendelijk spaans biologische gerechten
1                    1              1              1          1               1      1                     0
2                    1              1              1          1               1      0                     1
3                    1              1              1          1               0      0                     1
  certificaat van uitmuntendheid tripadvisor 2016 gebruik streekproducten iens topper 2016 vegetarische gerechten
1                                               0                       0                0                      0
2                                               1                       1                1                      1
3                                               0                       1                0                      1
  romantisch zakelijk aan het water frans wijnbar
1          0        0             0     0       0
2          1        1             0     0       0
3          1        1             1     1       1

Возможность с dplyr и tidyr, хотя с использованием separate_rows означает, что я не сохранил оригинальную колонку. Вы можете объединиться на основе номеров строк или создать дубликат столбца "Теги" для использования в separate_rows,

Если в каждой ячейке есть только один экземпляр тега:

library(dplyr)
library(tidyr)
library(tibble)

df %>%
    rownames_to_column() %>% 
    separate_rows(Tags, sep = ", ") %>%
    mutate(Tags = gsub('"', "", Tags), n = 1) %>%
    spread(Tags, n, fill = 0)

Я добавил имена строк в набор данных, разделил "Теги", чтобы они были в отдельных строках, а не в одном столбце, удалил лишние кавычки вокруг некоторых имен тегов, а затем сделал фиктивный столбец из 1 для каждой строки перед распространением в широкий формат.

Если каждая строка может иметь несколько значений одной из строк символов:

df %>%
    rownames_to_column() %>% 
    separate_rows(Tags, sep = ", ") %>%
    mutate(Tags = gsub('"', "", Tags), n = 1) %>%
    distinct(rowname, Tags, .keep_all = TRUE) %>%
    spread(Tags, n, fill = 0)
Другие вопросы по тегам