Перебираем строки фрейма данных и используем его как ввод функции в r - PullRequest
2 голосов
/ 13 июля 2020

Я хочу l oop над таблицей с категориями, чтобы назначить подкатегорию столбцу в другом фрейме данных, называемом «данные». Текст написан вручную человеком и представляет собой символьное поле, которое содержит около 100 слов, но имеет динамическую c длину. Я хочу проверить, находится ли слово, указанное в 'search_pat', в поле 'text', если оно есть, и 'category' также совпадает, подкаталог должен быть назначен. Функция apply, которую я выполняю в приведенном ниже коде, дает мне результат : "cat1" "cat2"

Но мой желаемый результат - те же «данные» фрейма данных, но с заполненными значениями (если применимо) для столбца «подкатегория».

Мой реальный фрейм данных «данные» 400 000 строк, а таблица категорий сейчас составляет около 100 строк, но в будущем будет расширена. У меня это работает с for-l oop, но мне это кажется довольно неэффективным. Моя цель - сделать код более эффективным.

См. Пример, приведенный ниже.

# Create example data
data <- data.frame('text' = rep(c('blabla FOO blabla', 'blabla test','bla BAR blablabla', 'test BOO blabla'),2),
                   'category' = c('X', 'Y', 'Z', 'X', 'X', 'X', 'X', 'Z'),
                   'subcat' = rep(NA, 8))

categories <- data.frame('search_pat' = c('FOO', 'BAR', 'BOO', 'BOO'),
                         'category' = c('X', 'Z', 'X', 'Z'),
                         'subcat' = c('cat1', 'cat2', 'cat3', 'cat4'))

# Function for assigning the subcategory to the data
assign_subcat <- function(df, searchterm, category, subcat){
  bool_mask <- (grepl(searchterm, df$text) & (df$category == category))
  df$subcat[bool_mask] <- subcat
}

# Loop over the categories dataframe to assign subcategory on the data
apply(categories, MARGIN = 1, FUN = function(x) assign_subcat(df = data,
                                                              x['search_pat'],
                                                              x['category'],
                                                              x['subcat']))

# Desired result
       text           category subcat
1 blabla FOO blabla        X     cat1
2       blabla test        Y     NA
3 bla BAR blablabla        Z     cat2
4   test BOO blabla        X     cat3
5 blabla FOO blabla        X     cat1
6       blabla test        X     NA
7 bla BAR blablabla        X     NA
8   test BOO blabla        Z     cat4

1 Ответ

1 голос
/ 13 июля 2020

Вы можете использовать операцию левого соединения для достижения ожидаемого результата. С помощью пакета dplyr вы можете сначала создать столбец search_pat, в котором будут храниться ключи, которые вы ищете (в вашем примере "FOO" и "BAR" извлекаются благодаря функции str_extract из пакета stringr), затем вы присоединяетесь к search_pat и category, а затем отбрасываете ненужные столбцы.

library(dplyr)

data %>% 
  mutate(search_pat = stringr::str_extract(text, paste(categories$search_pat, collapse = "|"))) %>% 
  left_join(categories, by = c("search_pat", "category"), suffix = c("_to_be_removed", "")) %>% 
  select(-search_pat, -subcat_to_be_removed)

#                text category subcat
# 1 blabla FOO blabla        X   cat1
# 2       blabla test        Y   <NA>
# 3 bla BAR blablabla        Z   cat2
# 4 blabla FOO blabla        X   cat1
# 5       blabla test        Z   <NA>
# 6 bla BAR blablabla        X   <NA>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...