【问题标题】:Partial String Match with matching regular expression in new column - R部分字符串匹配与新列中的匹配正则表达式 - R
【发布时间】:2016-01-04 00:04:21
【问题描述】:

我正在尝试将数据集中列的内容与一串正则表达式进行部分匹配。然后,我想匹配在新列中返回特定匹配正则表达式的行。我的实际数据集很大(130 万行),包含 300 个正则表达式,因此找到一种自动执行此操作的方法很重要,这样添加新的正则表达式就不需要代码调整。

演示:

try.dat<-data.frame(c(1:10),c("hello","goodbye","tidings","partly","totally"))
names(try.dat)[1]<-"num"
names(try.dat)[2]<-"words"
try.dat

在这种情况下,如果一个正则表达式是“ly”,我希望在匹配行(部分地,完全地)中有一个带有“ly”的列,而在其他行中有一些“不匹配”的术语。我已经成功地使用 grepl (subset not based on exact match) 成功地对数据进行了子集化,效果很好,但下一步我真的很挣扎!

我在尝试这个方面取得了一些的进展,主要是基于我已经适应的这个代码建议 (partial string matching R):

pattern<-c("ll|ood")
matching<-c("ood","ll")
regexes<-data.frame(pattern,matching)
output_vector<-character(nrow(try.dat))
for(i in seq_along(regexes)){
output_vector[grepl(x=try.dat$words,pattern=regexes[[i]][1])] <- regexes    [[i]][2]    
}
try.dat$match<- output_vector
try.dat

如您所见,这会在匹配的行旁边返回一个“1” - 到达那里,但我已经没有想法了!我想知道是否有人可以提供任何指示?

谢谢!

【问题讨论】:

  • 不确定你想要什么作为输出。带有正则表达式匹配索引的新match 列?您可以发布所需的输出列吗?
  • 是的,你是对的@PierreLafortune,所以对于“部分”这个词和正则表达式“ly”,我想在匹配列中使用“ly”。为了扩大范围,我的实际数据集基于拼写/商品名称等不同的药物处方的项目代码 - 我的正则表达式将提供指向标准化短语的链接,然后允许我将项目代码与实际产品相匹配分发 - 很难解释何时数据集太大而无法发布!
  • 如果你想知道哪个模式匹配,你需要做两个greps。您还应该有一个应急计划,以防两者匹配。如果你统一你的例子,你的问题会更清楚。您最初谈论匹配"ly",但当您共享代码时,它是"ll|ood"
  • 道歉@Gregor,以便澄清:word = hello,reg ex = ll,match = ll
  • 您介意给出一个双 grep 的简单示例吗?我对 stringr 有一点尝试,但我到了它似乎不起作用的地步,所以寻求其他途径

标签: regex r grepl


【解决方案1】:

基于扩展至 10M 行的数据集(Macbook Pro OS X)对两者的运行时间比较:

try.dat<-data.frame(c(1:10000000),c("hello","goodbye","tidings","partly","totally"))
system.time(try.dat[str_extract(try.dat$words,"ll|ood"),"match"])

用户系统已过

5.167 0.208 5.348

system.time(for (i in 1: length(patt)) {try.dat[grep(patt[i], try.dat$words), "match"] <- patt[i]})

用户系统已过

0.311 0.041 0.377

目前的迹象表明,基本 R 版本显着提高了效率。将在我的实际数据集上尝试这个(400

【讨论】:

    【解决方案2】:

    基本 R 选项。只是因为。

    patt <- c("ll", "ood")
    for (i in 1: length(patt)) {
      try.dat[grep(patt[i], try.dat$words), "match"] <- patt[i]
    }
    try.dat
    #    num  words match
    #1    1   hello    ll
    #2    2 goodbye   ood
    #3    3 tidings  <NA>
    #4    4  partly  <NA>
    #5    5 totally    ll
    #6    6   hello    ll
    #7    7 goodbye   ood
    #8    8 tidings  <NA>
    #9    9  partly  <NA>
    #10  10 totally    ll
    

    【讨论】:

    • 谢谢 - 有趣且总是很高兴看到基本的 R 做事方式!出于兴趣,每个都有运行时间 - 请参阅下面的答案
    【解决方案3】:

    我认为这样可以吗?

    library(stringr)
    try.dat$match = str_extract(try.dat$words, "ll|ood")
    try.dat
    #    num   words match
    # 1    1   hello    ll
    # 2    2 goodbye   ood
    # 3    3 tidings  <NA>
    # 4    4  partly  <NA>
    # 5    5 totally    ll
    # 6    6   hello    ll
    # 7    7 goodbye   ood
    # 8    8 tidings  <NA>
    # 9    9  partly  <NA>
    # 10  10 totally    ll
    

    默认行为是提取第一个匹配项。如果您想获取所有匹配项,您可以使用 str_extract_all,但在这种情况下您需要一个 non-data.frame 设置来处理不同数量的匹配项。

    【讨论】:

    • 太棒了,谢谢!在这个数据集上为我工作 - 出于对你的兴趣,因为我的实际数据集有很多 reg ex,我快速检查以确保 str_extract 理解汇总字符串,即 pattern
    • 很高兴听到。作为未来的说明,如果您将最终结果的几行作为示例输出包含在内,您的问题会更加更清楚。当我发布这个答案时,我已经阅读了你的问题三遍,我只有大约 70% 的把握这是你想要的。
    • 感谢您的指点,这是关于堆栈溢出和数据处理主题的新手,很高兴知道什么会使事情变得更清晰。作为进一步说明,这个解决方案非常适合我的实际数据集......由于提取第一个匹配项(如您所述),必须调整几个正则表达式以更具体,但这非常容易并且比拥有多个匹配项更可取确实会使进一步的分析复杂化。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 2021-02-09
    相关资源
    最近更新 更多