3

How can I use purrr::map() to return the result of the for loop of the example:

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"
1

4 Answers 4

4

Actually, you do not need any of the ReduceMap functions. Just use str_replace_all its vectorized

library(stringr)
str_replace_all(vct_string, set_names(df_correction$replacement, df_correction$pattern))

[1] "old car"   "new car"   "house"     "old house"
Sign up to request clarification or add additional context in comments.

1 Comment

Bingo! I was trying to use this function but couldn't thought of using set_names. +1
3

You have to recursively modify your vector so in my opinion this is classic case of usage of reduce family function here. So do this, where you will have to pass your vector to .init argument of purrr::reduce to get the desired output

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"

This will even do multiple replacements in elements of given vector. see this

#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"

Comments

1

First write a function for the replacements

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")

Then you can pass that function as an argument in purrr::map

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

Since you are using a mapping table to replace individual words, you can actually use map in a second function to get your desired results.

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)

Comments

1

Here is how you could do it with 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"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.