使用pmap将不同的正则表达式应用于小标题中的不同变量吗?

时间:2018-10-30 18:24:32

标签: r purrr

我正在尝试将不同的正则表达式应用于不同的变量。例如,我用小标题列出了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 :(得分:2)

使用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 

答案 1 :(得分:1)

您无需创建函数(您的函数实际上是问题的根源):您可以直接使用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