使用purrr::map将向量重写为for循环形式

3
我该如何使用 purrr::map() 来返回以下示例中的 for 循环结果呢?
vct_string <- c("old ccar","new carr", "house", "oold house")

df_correction <- data.frame(
  pattern  = c("ccar", "carr", "oold"),
  replacement = c("car", "car", "old"),
  stringsAsFactors = FALSE
)

for(i in 1:nrow(df_correction)){
  vct_string <- pmap(df_correction, gsub, x = vct_string)[[i]]
}

> vct_string
[1] "old car"   "new car"   "house"     "old house"

看起来这个现有的问题有一个适用于你的问题的答案: https://dev59.com/fLnoa4cB1Zd3GeqPIwjC - Jacob Rothschild
4个回答

4
实际上,您不需要使用任何 ReduceMap 函数。只需使用 str_replace_all ,它是矢量化的。
library(stringr)
str_replace_all(vct_string, set_names(df_correction$replacement, df_correction$pattern))

[1] "old car"   "new car"   "house"     "old house"

1
太棒了!我一直在尝试使用这个函数,但没想到可以用set_names。+1 - AnilGoyal

3

你需要递归修改向量,因此我认为这是在此处使用reduce函数族的经典用例。因此,要做到这一点,请将向量传递给purrr::reduce.init参数以获得所需的输出。

purrr::reduce(seq(nrow(df_correction)), .init = vct_string, ~ gsub(df_correction$pattern[.y], df_correction$replacement[.y], .x))

#> [1] "old car"   "new car"   "house"     "old house"

这将会在给定向量中的元素中进行多次替换。查看此链接

#modified example
vct_string <- c("old ccar","new carr", "house", "oold carr")

purrr::reduce(seq(nrow(df_correction)), .init = vct_string, ~ gsub(df_correction$pattern[.y], df_correction$replacement[.y], .x))
[1] "old car" "new car" "house"   "old car"

1

首先编写一个函数来进行替换操作。

word_correct <- function(string) {
  df_correction <- data.frame(
    pattern  = c("old ccar", " new carr", "oold house", "house"), # changed from OP
    replacement = c("car", "car", "old", "house"),
    stringsAsFactors = FALSE
  )
  df_correction[ which(df_correction$pattern == string), "replacement"]
}

# Testing
word_correct("oold")
word_correct("ccar")

然后您可以将该函数作为参数传递给purrr::map

map_chr(vct_string, word_correct) # using map_chr to return a vector instead of a list which is what map returns

既然您正在使用映射表来替换单个单词,您实际上可以在第二个函数中使用map来获得所需的结果。

vct_string <- c("old ccar","new carr", "house", "oold house")

single_word_correct <- function(string) {
  
  df_correction <- data.frame(
    pattern  = c("ccar", "carr", "oold"),
    replacement = c("car", "car", "old"),
    stringsAsFactors = FALSE
  )
  if(string %in% df_correction$pattern){
    df_correction[ which(df_correction$pattern == string), "replacement"]
  } else {
    string
  }
}
multi_word_correct <- function(string){
  strings <- strsplit(string, " ")[[1]]
  paste(map_chr(strings, single_word_correct), collapse = " ")
}

map_chr(vct_string, multi_word_correct)

1

以下是使用base :: Reduce的方法:

Reduce(function(x, y) {
  gsub(df_correction[y, 1], df_correction[y, 2], x)
}, init = vct_string, 1:nrow(df_correction))

[1] "old car"   "new car"   "house"     "old house"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接