【问题标题】:Regex R: Remove strings from text by using a vector string正则表达式 R:使用向量字符串从文本中删除字符串
【发布时间】:2020-12-17 03:11:13
【问题描述】:
names <- c('Laars Anderson', 'Peter Grabowski')
text <- c('Laars Anderson needs to bla bla bla, reply from Peter Grabowski')
output <- c('needs to bla bla bla, reply from')

我正在使用正则表达式来清理我的文本以进行文本挖掘。文本主要是关于电子邮件对话,其中包含许多不相关的词,如姓名、电子邮件等。

我有员工姓名列表,并希望使用此姓名列表从文本电子邮件中删除他们的姓名。

谢谢!

【问题讨论】:

    标签: r regex string


    【解决方案1】:

    您也可以使用“stringi”包中的stri_replace_all:

    library(stringi)
    stri_replace_all_fixed(text, names, "", vectorize_all=FALSE)
    ## [1] " needs to bla bla bla, reply from "
    

    用trimws 去掉前导和尾随空格。

    【讨论】:

    • 这个老问题 - stackoverflow.com/a/26171700/496803 - 可以以矢量化方式适用于这类事情,包括来自 Flodel 的一个非常有趣的 Reduce 选项 - Reduce(function(str, args) gsub(args, "", str), names, init = text)
    • 我最初打算发布一个for 循环,因为fixed = TRUE 的选项似乎也很有帮助。 (在那边给你+1)。 Reduce 的方法也很棒!
    • Reduce 改编版在我第一次看到它时完全让我感到困惑。还有第二次和第三次。
    • Warning messages: 1: In stri_replace_all_fixed(text, names, "", vectorize_all = FALSE) : empty search patterns are not supported 这里有一些边缘情况,实际的名称向量在 10,000 左右,并且文本可能包含丹麦字符。以防万一,我事先对文本进行了一些清理以删除特殊字符。谢谢,非常感谢
    • @A5C1D2H2I1M1N2O1R2T1 谢谢你,我仍然发现for 循环很慢,但它暂时有效。一旦我对原因有了更好的了解,我会提出另一个问题。
    【解决方案2】:

    这类似于@Ronak 的答案,但使用正确的单词边界和空格模式来实现更简洁的方法:

    names <- c('Laars Anderson', 'Peter Grabowski')
    text <- 'Laars Anderson needs to bla bla bla Peter Grabowski, reply from Peter Grabowski'
    regex <- paste0("\\b\\s*(?:", paste0(names, collapse="|"), ")\\b\\s*")
    output = trimws(gsub(regex, " ", text))
    output
    
    [1] "needs to bla bla bla , reply from"
    

    如果你的 names 向量真的很大,以至于正则表达式引擎无法处理交替的大小,那么你总是可以迭代并进行替换:

    names <- c('Laars Anderson', 'Peter Grabowski')
    text <- 'Laars Anderson needs to bla bla bla Peter Grabowski, reply from Peter Grabowski'
    for (name in names) {
        text <- gsub(paste0("\\b\\s*", name, "\\s*\\b"), "", text)
    }
    text <- trimws(text)
    text
    
    [1] "needs to bla bla bla, reply from"
    

    【讨论】:

    • 谢谢,你知道这个错误吗? Error in gsub(regex, " ", text) : assertion 'tree-&gt;num_tags == num_tags' failed in executing regexp: file 'tre-compile.c', line 634 我的名字向量很长,超过 10,000 个用户名。替代方案我发现有些人要求使用 qdap 库中的 mgsub 或将此用户名向量拆分为更小的块
    • @AfiqJohari 我实际上并不熟悉该错误,但我知道原因。就是变化太大了。让我用解决方法编辑我的问题。
    • @AfiqJohari,如果for 循环看起来很慢,我想知道是否有理由使用fixed = TRUE 切换到更简单的gsub,而不是处理单词边界和空格。有什么想法吗,蒂姆?
    • @A5C1D2H2I1M1N2O1R2T1 如果fixed=TRUE,它将在零长度模式Error in gsub(pattern = name, replacement = "", comment, fixed = TRUE) : zero-length pattern上失败
    • @A5C1D2H2I1M1N2O1R2T1 我收回我之前的评论。将 fixed 设置为 TRUE 意味着我们不能使用正则表达式替换,所以很遗憾这不是一个选项。但是,我们可以尝试删除单词边界和空格。这可能会加快速度。
    【解决方案3】:

    你可以使用:

    names <- c('Laars Anderson', 'Peter Grabowski')
    text <- c('Laars Anderson needs to bla bla bla, reply from Peter Grabowski')
    
    gsub(paste0(names, collapse = ' | '), '', text)
    #[1] "needs to bla bla bla, reply from"
    

    【讨论】:

    • 感谢@ronak,该解决方案适用于上述可重现的示例,但我想对要使用的向量名称的实际长度有一些限制。 Error in gsub(paste0(names, collapse = " | "), "", text) : assertion 'tree-&gt;num_tags == num_tags' failed in executing regexp: file 'tre-compile.c', line 634,我尝试了qdap的mgsub替代功能,但同样的问题
    【解决方案4】:

    如果names 对于正则表达式引擎来说太长,您可以使用Reduce 循环到每个名称。

    trimws(Reduce(function(x,y) gsub(y, "", x), paste0("\\b", names, "\\b"), text))
    #[1] "needs to bla bla bla, reply from"
    

    或使用 perl:

    trimws(gsub(paste0("\\b", names, "\\b", collapse="|"), "", text, perl=TRUE))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 2021-01-17
      • 2014-06-20
      相关资源
      最近更新 更多