【问题标题】:Replace multiple words in multiple strings替换多个字符串中的多个单词
【发布时间】:2022-01-17 11:52:43
【问题描述】:

我想根据另一个数据框中的原始单词和替换单词替换向量中的单词。举个例子:

要更改的字符串向量:

my_words <- c("example r", "example River", "example R", "anthoer river",
        "now a creek", "and another Ck", "example river tributary")

要替换的词的数据框和对应的替换词:

my_replace <- data.frame(
  original = c("r", "River", "R", "river", "Ck", "creek", "Creek"),
  replacement = c("R", "R", "R", 'R', "C", "C", "C"))

我想用向量my_wordsmy_replace$replacement 中的相应值替换my_replace$original 中出现的任何单词。我尝试使用stringr::str_replace_all(),但它替换了字母/单词的所有实例,而不是整个单词(例如“another”变成了“anotherR”),这是不可取的。

我想做的伪代码:

str_replace_all(my_words, my_replace$original, my_replace$replacement)

期望的输出:

"example R", "example R", "example R", "another R", "now a C", "and another C", "example R tributary"  

我确实找到了使用for 循环的解决方案,但鉴于我的数据集很大,for 循环选项太慢了。非常感谢任何建议。

【问题讨论】:

    标签: r regex string replace


    【解决方案1】:

    这是一种sub 方法,它只进行一次替换:

    my_words <- c("example r", "example River", "example R", "anthoer river",
        "now a creek", "and another Ck", "example river tributary")
    
    output <- gsub("\\b([rR])(?:iver)?\\b|\\b([cC])(?:ree)?k\\b", "\\U\\1\\U\\2", my_words, perl=TRUE)
    output
    
    [1] "example R"           "example R"           "example R"
    [4] "anthoer R"           "now a C"             "and another C"
    [7] "example R tributary"
    

    由于所有河流和小溪出现的替换分别只是 RC,因此我们可以捕获每个可能匹配的第一个字母,然后使用这些字母的大写版本进行替换。

    【讨论】:

    • 我应该给出一个更详细的例子,在我的完整数据集中有 20-30 个其他替代替换代码,并且并非都是单个字母(例如,“pond”和“Pond”变成“Pnd”和“声音”和“声音”变成“Snd”)。所以我需要一个使用my_replace$replacement. 中的值的解决方案,而不是依赖于删除部分单词。
    • @flee 对于 20-30 个其他目标匹配,您可以在我的答案中扩大交替以包括它们。
    【解决方案2】:

    您需要从my_words$original 中的单词构建一个基于动态单词边界的模式,然后使用stringr::str_replace_all 替换为相应的值。注意original 短语需要按长度降序排序,以使较长的字符串首先匹配:

    my_words <- c("example r", "example River", "example R", "anthoer river", "now a creek", "and another Ck", "example river tributary")
    my_replace <- data.frame(original = c("r", "River", "R", "river", "Ck", "creek", "Creek"), replacement = c("R", "R", "R", 'R', "C", "C", "C"))
    sort.by.length.desc <- function (v) v[order( -nchar(v)) ]
    library(stringr)
    regex <- paste0("\\b(",paste(sort.by.length.desc(my_replace$original), collapse="|"), ")\\b")
    str_replace_all(my_words, regex, function(word) my_replace$replacement[my_replace$original==word][[1]][1])
    

    输出:

    [1] "example R"           "example R"           "example R"           "anthoer R"           "now a C"             "and another C"       "example R tributary"
    

    正则表达式将是\b(River|river|creek|Creek|Ck|r|R)\b,它将匹配里面的任何单词作为一个完整的单词。

    【讨论】:

      【解决方案3】:
      library(stringi)
      
      stri_replace_all_regex(my_words, "\\b" %s+% my_replace$original %s+% "\\b", my_replace$replacement, vectorize_all = FALSE)
      
      [1] "example R" "example R" "example R" "anthoer R" "now a C" "and another C" "example R tributary"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-05
        • 1970-01-01
        • 2016-08-29
        • 2020-05-30
        • 1970-01-01
        • 2019-01-29
        相关资源
        最近更新 更多