【问题标题】:How to improve this code? Extract info using Regex如何改进这段代码?使用正则表达式提取信息
【发布时间】:2019-06-19 21:47:33
【问题描述】:

我有这个数据框,其中包含一些我正在尝试提取的数据,我实际上没有问题,但我觉得应该有更好/更优雅的方法来做到这一点。

所以,我有这个字符串

CVEGEO=0901500011337<BR>CVE_ENT=09<BR>CVE_MUN=015<BR>CVE_LOC=0001<BR>CVE_AGEB=1337<BR>

136 次,我对 MUN=(.*) and AGEB=(.*) 感兴趣

获取我使用的信息:

test1 <- sub(".*_MUN=(.*)<BR>CVE_LOC=0001<BR>CVE_AGEB=(.*)<.*", "\\1_\\2", L1_AGEB$description)
str_split_fixed(test1, "_", 2)

它工作得很好,但是,就像我说的,这只是为了学术/改进目的。有没有更简单/优雅的方法?

谢谢

【问题讨论】:

    标签: r regex


    【解决方案1】:

    一定要看看rex包, 它有一个学习曲线, 但它可能非常漂亮:

    library(rex)
    
    rex::re_matches("CVEGEO=0901500011337<BR>CVE_ENT=09<BR>CVE_MUN=015<BR>CVE_LOC=0001<BR>CVE_AGEB=1337<BR>",
                    pattern = rex::rex(
                      "MUN=",
                      capture(any_numbers, name = "MUN"),
                      anything,
                      "AGEB=",
                      capture(any_numbers, name = "AGEB")
                    ))
      MUN AGEB
    1 015 1337
    

    【讨论】:

      【解决方案2】:

      This answer 效率低下。在这里,也许,我们只使用[0-9] 而不是\d,这可能在时间和空间复杂性方面表现得更好,我只是在猜测,就像你提到的那样,你原来的表达只是好吧,当我们使用正则表达式时,通常不推荐环视,也不推荐任何其他花哨的方法。

      MUN=([0-9]+).+AGEB=([0-9]+)
      

      Demo

      我很确定应该有其他方法来改进我们希望在这里完成的工作,但关键是,您的原始表达已经走在正确的道路上,但可能不是正确的,为此原因我们可能会牺牲所需的优雅。

      请查看 cmets 中的其他观点,我只是作为参考,在这里并没有真正的意见/建议,即使听起来可能不是这样。

      参考文献

      【讨论】:

      • 我会小心 2013 年的链接帖子。今天,\d 匹配 UTF-8/32 正则表达式中的这些 Unicode 范围:[0-9٠-٩۰-۹߀-߉०-९০-৯੦-੯૦-૯୦-୯௦-௯౦-౯೦-೯൦-൯෦-෯๐-๙໐-໙༠-༩၀-၉႐-႙០-៩᠐-᠙᥆-᥏᧐-᧙᪀-᪉᪐-᪙᭐-᭙᮰-᮹᱀-᱉᱐-᱙꘠-꘩꣐-꣙꤀-꤉꧐-꧙꧰-꧹꩐-꩙꯰-꯹0-9?-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-??-?]
      • 随着性能的提高,类中的范围是最慢的,其次是序列。 Speedwise,\d 是一个内在的 api 函数isdigit(),它比其他函数花费的时间更短。 Regex1: [0123456789] Matches found per iteration: 62 Elapsed Time: 2.36 s, 2363.61 ms, 2363615 µs Matches per sec: 1,311,550 Regex2: [0-9] Matches found per iteration: 62 Elapsed Time: 2.62 s, 2620.44 ms, 2620444 µs Matches per sec: 1,183,005 Regex3: \d Matches found per iteration: 62 Elapsed Time: 2.20 s, 2196.97 ms, 2196974 µs Matches per sec: 1,411,031
      【解决方案3】:

      您可以使用带有 PCRE 正则表达式的 regmatches / regexpr 方法,该方法将在已知“前缀”之后提取 1+ 位:

      x <- "CVEGEO=0901500011337<BR>CVE_ENT=09<BR>CVE_MUN=015<BR>CVE_LOC=0001<BR>CVE_AGEB=1337<BR>"
      regmatches(x, regexpr("_MUN=\\K\\d+", x, perl=TRUE))
      ## => [1] "015"
      regmatches(x, regexpr("_AGEB=\\K\\d+", x, perl=TRUE))
      ## => [1] "1337"
      

      在线查看R demo

      正则表达式详细信息

      • _MUN= - _MUN 文字
      • \K - 匹配重置运算符,丢弃目前匹配的文本
      • \d+ - 1 位以上。

      perl=TRUE 的使用对于正则表达式的工作至关重要。

      使用stringr 等效:

      library(stringr)
      str_extract(x, "(?<=_MUN=)\\d+")
      str_extract(x, "(?<=_AGEB=)\\d+")
      

      (?&lt;=...) 肯定后向仅检查紧靠当前位置左侧的模式匹配,但不消耗文本,即不将其放入匹配值中。

      还有一个奇特的解决方案,stringr::str_match 将结果一次性捕获到第 2 列和第 3 列:

      library(stringr)
      str_match(x, "_MUN=(\\d+).*_AGEB=(\\d+)")
      #      [,1]                                        [,2]  [,3]  
      # [1,] "_MUN=015<BR>CVE_LOC=0001<BR>CVE_AGEB=1337" "015" "1337"
      

      【讨论】:

        【解决方案4】:

        我们可以通过将输入转换为 DCF 格式来完全解析整个输入。这样做的好处是可以轻松地随后提取任何字段。

        假设在最后的注释中输入x,我们可以用换行符替换&lt;BR&gt;,用冒号替换=,然后使用read.dcf读取剩下的内容。没有使用任何包。

        x2 <- gsub("=", ":", gsub("<BR>", "\n", x))
        read.dcf(textConnection(x2))
        

        给出这个字符矩阵:

             CVEGEO          CVE_ENT CVE_MUN CVE_LOC CVE_AGEB
        [1,] "0901500011337" "09"    "015"   "0001"  "1337"  
        [2,] "0901500011337" "09"    "015"   "0001"  "1337"  
        [3,] "0901500011337" "09"    "015"   "0001"  "1337"  
        

        使用 magrittr 包的变体是:

        library(magrittr)
        x %>%
          gsub("<BR>", "\n", .) %>%
          gsub("=", ":", .) %>%
          textConnection %>%
          read.dcf
        

        注意

        x <- "CVEGEO=0901500011337<BR>CVE_ENT=09<BR>CVE_MUN=015<BR>CVE_LOC=0001<BR>CVE_AGEB=1337<BR>"
        x <- rep(x, 3)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-28
          • 2018-03-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多