Использование pmap для применения различных регулярных выражений к различным переменным в таблице? - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь применить разные регулярные выражения к разным переменным в таблице. Например, я сделал тиббл листинг 1) имя переменной, которую я хочу изменить, 2) регулярное выражение, которое я хочу сопоставить, и 3) строка замены. Я хотел бы применить регулярное выражение / замену к переменной в другом фрейме данных.

Таким образом, моя «конфигурация» выглядит так:

test_config <-  dplyr::tibble(
  string_col = c("col1", "col2", "col3", "col4"),
  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")
)

Таким образом, цель состоит в том, чтобы заменить другую строку пустой строкой в ​​каждом столбце / переменной 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")
)

Я могу делать то, что хочу, с помощью цикла 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 in UseMethod("tbl_vars") : 
  no applicable method for 'tbl_vars' applied to an object of class "character"
Called from: tbl_vars(tbl)

Может ли кто-нибудь из вас предложить способ использовать pmap для того, что я хочу, или есть другой или лучший подход к решению проблемы?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Другой метод, использующий map2_dfc (суффикс _dfc также доступен для pmap):

library(dplyr)
library(purrr)

map2_dfc(test_target, seq_along(test_target), 
         ~sub(test_config$pattern[.y], 
              test_config$replacement[.y], .x))

или imap_dfc (обратите внимание, что при этом вы потеряете имена столбцов):

imap_dfc(unname(test_target), 
         ~sub(test_config$pattern[.y], 
              test_config$replacement[.y], .x))

Выход:

# A tibble: 5 x 4
  col1  col2  col3  col4 
  <chr> <chr> <chr> <chr>
1 Foo   Foo   Foo   NULL 
2 bar   bar   bar   NA   
3 ""    .     .     Foo  
4 NA    ""    NA    .    
5 NULL  NULL  ""    bar 
0 голосов
/ 30 октября 2018

Вам не нужно создавать функцию (ваша функция на самом деле является источником проблемы): вы можете использовать str_replace_all напрямую.

pmap_dfr(
  list(test_target,
       test_config$pattern,
       test_config$replacement),
  str_replace_all
)

# A tibble: 5 x 4
  col1  col2  col3  col4 
  <chr> <chr> <chr> <chr>
1 Foo   Foo   Foo   NULL 
2 bar   bar   bar   NA   
3 ""    .     .     Foo  
4 NA    ""    NA    .    
5 NULL  NULL  ""    bar  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...