【问题标题】:Handling ties in multiple grepl statements处理多个 grepl 语句中的关系
【发布时间】:2017-11-28 19:50:37
【问题描述】:

我正在处理一项需要清除大量杂乱字符串数据的任务。
我已经解决了大多数问题,但遇到了两个问题:

  1. 使用多个 grepl 语句时的关系
  2. 我觉得可以简化很多代码,但我不知道如何简化

让我们考虑这个最小的例子:

names 是一个字符向量,存储了 3 个不同的人的名字,写法不同

names 应简化(重新编码),以便以相同方式存储多次出现的人名

让我们假设 Johnatan 是第一约翰,
约翰尼和约翰尼都是第二约翰,
John、John D.、John Doe 是第三约翰。

凭借我有限的R 知识,我得到了这个解决方案:

names <- c("John", "Johnatan", "Johnnie", "John D.", "John Doe", "johnnie")

names[grepl("johna", names, ignore.case = TRUE)] <- "First John"
names[grepl("johnn", names, ignore.case = TRUE)] <- "Second John"
names[grepl("john d*", names, ignore.case = TRUE)] <- "Third John"

此时有john,我不知道如何重新编码为Third John

names[grepl("john", names, ignore.case = TRUE)]

将收集names 中的所有约翰。

问题:

我该如何处理这种关系,希望以某种方式,比我目前所写的更优雅?

感谢您的任何提示和建议。

【问题讨论】:

    标签: r regex grepl


    【解决方案1】:

    您可以为"john" 使用单词边界 (\\b):

    names <- c("John", "Johnatan", "Johnnie", "John D.", "John Doe", "johnnie")
    names2 = names
    
    names2[grepl("johna", names, ignore.case = TRUE)] <- "First John"
    names2[grepl("johnn", names, ignore.case = TRUE)] <- "Second John"
    names2[grepl("john(\\b|\\sd.*)", names, ignore.case = TRUE)] <- "Third John"
    

    或与case_when 来自dplyr

    library(dplyr)
    names = case_when(grepl("johna", names, ignore.case = TRUE) ~ "First Join",
                      grepl("johnn", names, ignore.case = TRUE) ~ "Second Join",
                      grepl("john(\\b|\\sd.*)", names, ignore.case = TRUE) ~ "Third Join")
    

    注意:

    • \\b 匹配单词边界,可以是空格或标点符号。例如,johnatan 将不匹配,因为 john 跟在另一个字母 a 之后,而不是单词边界。

    • \\s 匹配空格。

    • d.* 匹配 d 后跟任何 (.) 零次以上。

    • ( | ) 是匹配| 左侧或右侧的捕获组。

    • john(\\b|\\sd.*) 匹配 john 后跟单词边界或空格后跟 d 以及任何零次或多次。因此匹配 "john""john d.""john doe"ignore.case = TRUE 处理这些情况)。

    结果:

    > names2
    [1] "Third John"  "First John"  "Second John" "Third John"  "Third John"  "Second John"
    

    【讨论】:

    • 我不知道 boudry "john(\\b|\\sd*)" 这个词,它看起来很有希望。我将使用其他我需要工作的名称对其进行测试,看看是否可以解决问题 #1。谢谢!
    【解决方案2】:
    temp = c(Johnatan = "First John", johnnie = "Second John", John = "Third John")
    temp[apply(X = sapply(names(temp),
                     function(x) grepl(pattern = x,
                                       x = names,
                                       ignore.case = TRUE)),
          MARGIN = 1,
          FUN = function(x) head(which(x), 1))]
    #         John      Johnatan       johnnie          John          John       johnnie 
    # "Third John"  "First John" "Second John"  "Third John"  "Third John" "Second John" 
    

    【讨论】:

    • 这显然可以完成工作,但为了使用它,我必须消化你的代码。太多的新东西让我无法理解
    • 太好了,谢谢你的建议。将在几秒钟内进行测试。
    • d.b 再次感谢您提供的代码 - 当前面的步骤已经完成时,它与第三个约翰一起工作。问题是我不知道如何将其扩展到更一般的用途并将其应用于其他名称等。但这可能是这里的主题。我认为@user 方法(让我了解更多关于正则表达式 statememts),虽然它不会缩短所有步骤,但可能更适合其他名称(或单词或我必须处理的任何类型的文本混乱)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    相关资源
    最近更新 更多