Этот вопрос очень похож на Использование pmap для применения различных регулярных выражений к разным переменным в таблице? , но отличается, потому что я понял, что моих примеров недостаточно для описания моей проблемы.
Я пытаюсь применить разные регулярные выражения к разным переменным в таблице. Например, я сделал тиббл листинг 1) имя переменной, которую я хочу изменить, 2) регулярное выражение, которое я хочу сопоставить, и 3) строка замены. Я хотел бы применить регулярное выражение / замена к переменной в другом фрейме данных. Обратите внимание, что в целевом тибле могут быть переменные, которые я не хочу изменять, и порядок строк в моем тибле «конфигурации» может не соответствовать порядку столбцов / переменных в моем «целевом» тибле.
Таким образом, моя «конфигурация» может выглядеть так:
test_config <- dplyr::tibble(
string_col = c("col1", "col2", "col4", "col3"),
pattern = c("^\\.$", "^NA$", "^$", "^NULL$"),
replacement = c("","","", "")
)
Я бы хотел применить это к целевому столу:
test_target <- dplyr::tibble(
col1 = c("Foo", "bar", ".", "NA", "NULL"),
col2 = c("Foo", "bar", ".", "NA", "NULL"),
col3 = c("Foo", "bar", ".", "NA", "NULL"),
col4 = c("NULL", "NA", "Foo", ".", "bar"),
col5 = c("I", "am", "not", "changing", ".")
)
Таким образом, цель состоит в том, чтобы заменить другую строку пустой строкой в пользовательском столбце / переменных test_target.
Результат должен быть таким:
result <- dplyr::tibble(
col1 = c("Foo", "bar", "", "NA", "NULL"),
col2 = c("Foo", "bar", ".", "", "NULL"),
col3 = c("Foo", "bar", ".", "NA", ""),
col4 = c("NULL", "NA", "Foo", ".", "bar"),
col5 = c("I", "am", "not", "changing", ".")
)
Я могу делать то, что хочу, с циклом for, например:
for (i in seq(nrow(test_config))) {
test_target <- dplyr::mutate_at(test_target,
.vars = dplyr::vars(
tidyselect::matches(test_config$string_col[[i]])),
.funs = dplyr::funs(
stringr::str_replace_all(
., test_config$pattern[[i]],
test_config$replacement[[i]]))
)
}
Вместо этого, есть ли более аккуратный способ сделать то, что я хочу?
До сих пор, думая, что purrr::pmap
был инструментом для работы, я создал функцию, которая принимает фрейм данных, имя переменной, регулярное выражение и значение замены и возвращает фрейм данных с одной измененной переменной. Он ведет себя как ожидалось:
testFun <- function(df, colName, regex, repVal){
colName <- dplyr::enquo(colName)
df <- dplyr::mutate_at(df,
.vars = dplyr::vars(
tidyselect::matches(!!colName)),
.funs = dplyr::funs(
stringr::str_replace_all(., regex, repVal))
)
}
# try with example
out <- testFun(test_target,
test_config$string_col[[1]],
test_config$pattern[[1]],
"")
Однако, когда я пытаюсь использовать эту функцию с pmap
, я сталкиваюсь с парой проблем:
1) есть ли лучший способ построить список для вызова pmap, чем этот?
purrr::pmap(
list(test_target,
test_config$string_col,
test_config$pattern,
test_config$replacement),
testFun
)
2) Когда я звоню pmap
, я получаю сообщение об ошибке:
Error: Element 2 has length 4, not 1 or 5.
Так что pmap
не рад, что я пытаюсь передать тиббл длины 5 как элемент списка, чьи другие элементы имеют длину 4 (я думал, что это переработает тиббл).
Обратите внимание, что ранее, когда я звонил pmap
с 4-х строчным тибблом, я получал другую ошибку,
Error in UseMethod("tbl_vars") :
no applicable method for 'tbl_vars' applied to an object of class "character"
Called from: tbl_vars(tbl)
Кто-нибудь из вас может предложить способ использовать pmap, чтобы делать то, что я хочу, или существует другой или лучший подход к решению проблемы?
Спасибо!