Обновление
На основе вашего обновленного вопроса приведена обновленная версия моего ответа.
На этот раз я просто использовал ваши входные данные как есть и не создалименованная функция. Вместо этого я положил все в одну трубу. Столбец found
должен указывать, сколько раз был найден шаблон, поэтому вам не нужны разные объекты, так как not_unique
, matched_not_found
, matches_found
.
Я взял идею из GenesRus (вкомментарии вашего вопроса), чтобы создать список-столбец и удалить его, но я не стал использовать этот подход, используя расширение / сводную ширину, а вместо этого выбрал map2 для циклического перебора столбцов description
и desc_map
.
library(tidyverse)
data %>%
mutate(pattern = list(data_map)) %>%
unnest %>%
rename(row_id = "id", map_id = "id1") %>%
mutate(v = map2_lgl(description, desc_map,
~ str_detect(.x, .y))) %>%
group_by(row_id) %>%
mutate(found = sum(v),
desc_map = ifelse(found == F, NA, desc_map),
map_id = ifelse(found == F, NA, map_id)) %>%
filter(v == T | (v == F & found == 0)) %>%
distinct %>%
select(-v)
Старый ответ
Ниже приведен более основанный на тидивсе подход, который должен дать тот же результат. «Должен», потому что я могу только догадываться, как выглядят ваши входные данные и ожидаемый результат. Несколько замечаний: (1) Я выбираю нормальные символьные векторы в качестве входных данных. Идентификаторы строк генерируются на лету. (2) Я поместил ваш подход в функцию под названием match_tbl
. (3) Я использовал функции Tidyverse в сочетании с оператором pipe. Это делает весь подход легко читаемым, а внешний вид выглядит как 'tidyverse-ish'. Однако, когда вы посмотрите на реальные функции пакетов tidyverse, вы увидите, что авторы обычно воздерживаются от использования оператора pipe внутри функций, поскольку он может легко выдавать ошибки. Используйте отладчик RStudio в конвейерной операции и попытайтесь углубиться в происходящее, и вы увидите, что это довольно грязно. Поэтому, если вы хотите сделать из него действительно стабильную функцию, отбросьте каналы и используйте вместо этого промежуточные переменные.
Данные и пакеты
library(tidyverse)
# some description data (not a dataframe but a normal char vector)
description <- c("This is a text description",
"Some words that won't match",
"Some random text goes here",
"and some more explanation here")
# patterns that we want to find (not a dataframe but a normal char vector)
pattern <- c("explanation","description", "text")
Функция, генерирующая желаемый выход: таблица соответствий
# a function which replaces your nested for loop
match_tbl <- function(.string, .pattern) {
res <- imap(.pattern,
~ stringr::str_detect(.string, .x) %>%
tibble::enframe(name = "row_id") %>%
dplyr::mutate(map_id = .y) %>%
dplyr::filter(value == T) %>%
dplyr::select(-"value"))
string_tbl <- .string %>%
tibble::enframe(name = "id") %>%
dplyr::select("id")
dplyr::bind_rows(res) %>%
dplyr::right_join(string_tbl, by = c("row_id" = "id"))
}
Вызов функции и выход
match_tbl(description, pattern)
> row_id map_id
> <int> <int>
> 1 1 2
> 2 1 3
> 3 2 NA
> 4 3 3
> 5 4 1