Если строковое значение «X» в df1 равно любому из строковых значений в df2, присвоите категорию «1» значению X в новом столбце в df1 в R

#r #dplyr #text-classification

#r #dplyr #текст-классификация

Вопрос:

В рамках задачи анализа и классификации свободного текста мне нужно присвоить новые категории некоторым ответам свободного текста в зависимости от того, какие комбинации слов они содержат.

У меня есть один фрейм данных tibble (df1) со всеми ответами в виде свободного текста (1 столбец, 1 ответ на строку) (около 17 тыс. строк), и у меня есть несколько более мелких фрагментов (df2 — df10), которые содержат некоторые ключевые термины (1 столбец, 1 термин в строке).

Все значения являются строками

Я пытаюсь написать некоторый R-код, который выполняет следующее:

Если строковое значение «X» из df1 равно ЛЮБОМУ из строковых значений в df2, присвоите строковое значение «Категория 1» значению «X» в соседнем столбце в df1.

Если строковое значение «X» из df1 равно ЛЮБОМУ из строковых значений в df3, присвоите строковое значение «Категория 2» значению «X» в соседнем столбце в df1.

И так далее для df4-df10.

Ниже приведен код, который я пробовал до сих пор. Для простоты, здесь я сопоставляю только с df2 (термины категории 1) и присваиваю ‘other’ всему остальному, что не соответствует.

 df1 %>%
  select(response) %>%
  mutate(
    category = case_when(
      df2$term %in% response ~ " Category 1",
      TRUE                ~ "other"
    )
  )
  

Я получаю следующую ошибку, когда запускаю это:

 Error: Problem with `mutate()` input `category`.
x Input `category` can't be recycled to size 16585.
i Input `category` is `case_when(df2$terms %in% responses~ "1", TRUE ~ "other")`.
i Input `category` must be size 16585 or 1, not 29
  

Очевидно, что существует проблема из-за разных размеров df1 и df2, и я уверен, что для этого есть простое решение, но я ходил по кругу в течение 2-3 часов, не в состоянии его найти. Я действительно не хочу прибегать к перечислению фактических терминов вместо того, чтобы ссылаться на них во фрейме данных.

Любая помощь была бы глубоко оценена, пожалуйста, и спасибо вам.

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

1. Попробуйте response %in% df2$term и посмотрите, работает ли это. Кроме того, можете ли вы опубликовать образцы данных в dput формате? Пожалуйста, отредактируйте вопрос с выводом dput(head(df1, 20)) и тем же для df2 .

2. @RuiBarradas — ваше предложение сработало! Большое вам спасибо

Ответ №1:

Эта полностью векторизованная функция, похоже, делает то, о чем просит вопрос.

 new_col <- function(X, String, Y){
  i <- X[[1]] %in% String
  X[[2]] <- "other"
  if(any(Y[[1]] %in% String)) X[[2]][i] <- "Category 1"
  X
}

new_col(df1, "M", df2)
  

Тестовые данные

 set.seed(2020)
df1 <- data.frame(col1 = sample(LETTERS, 50, TRUE))
df2 <- data.frame(col1 = sample(LETTERS, 10, TRUE))
  

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

1.Как это полностью векторизовано? new_col(df1, c("A", "B"), df2) не будет работать