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

#r #dataframe #nlp #tidyr

#r #фрейм данных #нлп #тидир

Вопрос:

У меня есть большой файл df с платформы опроса. столбцы содержат один вопрос(в качестве заголовка) со всеми возможными ответами. Я пытаюсь разделить каждый из этих столбцов ответов на новый набор столбцов (с именем ответа в качестве имени нового столбца).

после этого я хотел бы, чтобы в каждом новом столбце указывалось, отображается ли значение в исходном столбце(с «1»), чтобы упростить обработку данных

 dflt;-data.frame("name"= c("John","mark","bell","elsa"),"what do you like to   eat"=c("apple","fries apple","peach","bread"))  

оригинальный df

Имя Что.тебе.нравится.есть?
Джон Apple
Марк жареное яблоко
колокол персик
эльза хлеб

я использую этот код, который работает, но я уверен, что должен быть более эффективный/простой способ сделать это, так как у меня более 50 столбцов, подобных этому.

 dflt;-df %gt;%  separate(what.do.you.like.to.eat, c("apple","fries","peach","bread",NA ), remove = F) df[,3:6]lt;-"" {  df[,3] = with(df, ifelse(grepl("apple", df$what.do.you.like.to.eat,ignore.case = T),   paste('1', df[,3]),   paste("", df[,3])))  df[,4] = with(df, ifelse(grepl("fries", df$what.do.you.like.to.eat,ignore.case = T),   paste('1', df[,4]),   paste("", df[,4])))  df[,5] = with(df, ifelse(grepl("peach", df$what.do.you.like.to.eat,ignore.case = T),   paste('1', df[,5]),   paste("", df[,5])))  df[,6] = with(df, ifelse(grepl("bread", df$what.do.you.like.to.eat,ignore.case = T),   paste('1', df[,6]),   paste("", df[,6]))) }   

желаемый результат

Имя Что.тебе.нравится.есть? Apple картофель фри персик хлеб
Джон Apple 1
Марк жареное яблоко 1 1
колокол персик 1
эльза хлеб 1

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

1. Честно говоря, я изо всех сил пытаюсь понять, что это довольно расплывчато, поэтому не могли бы вы предоставить образец ваших данных и образец ожидаемого результата ?

2. только что сделал, отправил по ошибке без примера

Ответ №1:

Вы можете использовать purrr::map , чтобы применить свой вектор ответов и для каждого из них проверить их наличие в строке.

 library(tidyverse)  df lt;- data.frame(  name = c("John", "mark", "bell", "elsa"),  "what do you like to eat" = c("apple", "fries apple", "peach", "bread") )  ans lt;- c("apple", "fries", "peach", "bread")  map_dfc(ans,~ transmute(df, !!sym(.x) := str_detect(what.do.you.like.to.eat, .x))) %gt;%  bind_cols(df, .) #gt; name what.do.you.like.to.eat apple fries peach bread #gt; 1 John apple TRUE FALSE FALSE FALSE #gt; 2 mark fries apple TRUE TRUE FALSE FALSE #gt; 3 bell peach FALSE FALSE TRUE FALSE #gt; 4 elsa bread FALSE FALSE FALSE TRUE  

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

1. спасибо, это отлично работает, в том числе и со строками. есть ли возможность привязать столбец результатов с помощью функции bind_cols в определенном месте во фрейме данных.? (аналогично : dplyr::переместить(ans, .after = имя)

Ответ №2:

Хорошо, я сделал это, скажи мне, работает ли это для тебя :

 my_df lt;- data.frame("name" = c("John","mark","bell","elsa"),  "what do you like to eat" = c("apple","fries apple","peach","bread"),  stringsAsFactors = FALSE) my_var lt;- unique(sort(str_split(string = my_df$what.do.you.like.to.eat, pattern = " ", simplify = TRUE))) my_pos lt;- which(my_var == "") if (length(my_pos)) {  my_var lt;- my_var[-my_pos] } my_col lt;- c(colnames(my_df), my_var) my_miss lt;- setdiff(my_col, colnames(my_df)) my_df[my_miss] lt;- NA my_f lt;- function(x, y) {  my_var lt;- grep(pattern = colnames(my_df)[x], x = my_df[, y])  if (length(my_var)) {  my_df[my_var, x] lt;lt;- 1  } } lapply(3:ncol(my_df), function(x) my_f(x, 2))  

вы можете изменить эту часть на эту :

 my_df lt;- data.frame("name" = c("John","mark","bell","elsa"),  "what do you like to eat" = c("i like apple","i love fries apple","i'm kind of peach","bread all the way"),  stringsAsFactors = FALSE) my_var lt;- unique(sort(str_split(string =  my_df$what.do.you.like.to.eat, pattern = " ", simplify = TRUE))) my_food lt;- c("apple", "fries", "bread", "peach") my_var lt;- my_var[which(my_var %in% my_food)] my_pos lt;- which(my_var == "") if (length(my_pos)) {  my_var lt;- my_var[-my_pos] }  

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

1. это отлично работает с этим примером, так что спасибо. проблема в том, что в исходном df ответ в основном состоит из отдельных строк, таких как «я люблю есть яблоки»;» я очень люблю хлеб»; и т.д. есть ли способ определить my_var, чтобы он мог обнаружить такую строку, или ее нужно добавить вручную в эту переменную?