【问题标题】:How do I extract multiple character strings from one line using R如何使用 R 从一行中提取多个字符串
【发布时间】:2014-07-03 03:01:04
【问题描述】:

我想从一行中提取多个字符串。

假设我有以下文本行(通过网站的“readLines”函数获取):

line <- "abc:city1-street1-long1-lat1,ldjad;skj//abc:city2-street2-long2-lat2,ldjad;skj//abc:city3-street3-long3-lat3,ldjad;skj//abc:city3-street3-long3-lat3,ldjad;skj//"

我想提取以下内容以分隔行:

[1] city1-street1-long1-lat1
[2] city2-street2-long2-lat2
[3] city3-street3-long3-lat3
[4] city4-street4-long4-lat4

我希望有人能给我提示如何执行此任务。

【问题讨论】:

    标签: regex r text readlines


    【解决方案1】:

    regmatches 救援:

    regmatches(line,gregexpr("city\\d+-street\\d+-long\\d+-lat\\d+",line))
    #[[1]]
    #[1] "city1-street1-long1-lat1"
    #[2] "city2-street2-long2-lat2"
    #[3] "city3-street3-long3-lat3"
    #[4] "city3-street3-long3-lat3"
    

    【讨论】:

      【解决方案2】:

      stringi 包的解决方案:

      library(stringi)
      stri_extract_all_regex(line, "(?<=:).+?(?=,)")[[1]]
      ## [1] "city1-street1-long1-lat1" "city2-street2-long2-lat2" "city3-street3-long3-lat3" "city3-street3-long3-lat3"
      

      还有stringr 包:

      library(stringr)
      str_extract_all(line, perl("(?<=:).+?(?=,)"))[[1]]
      ## [1] "city1-street1-long1-lat1" "city2-street2-long2-lat2" "city3-street3-long3-lat3" "city3-street3-long3-lat3"
      

      在这两种情况下,我们都使用正则表达式。 在这里,我们匹配所有字符(非贪婪,即.+?) 发生在:, 之间。 (?&lt;=:) 表示积极的后视:: 将被匹配,但不包含在结果中。另一方面,(?=,) 是正向预测:, 必须匹配但不会出现在输出中。

      一些基准测试:

      lines <- stri_dup(line, 250) # duplicate line 250 times
      library(microbenchmark)
      microbenchmark(
         stri_extract_all_regex(lines, "(?<=:).+?(?=,)")[[1]],
         str_extract_all(lines, perl("(?<=:).+?(?=,)"))[[1]],
         regmatches(lines, gregexpr("city\\d+-street\\d+-long\\d+-lat\\d+", lines)),
         lapply(unlist(strsplit(lines,',')),
             function(x)unlist(strsplit(x,':'))[2]),
         lapply(strsplit(lines,'//'),
              function(x)
                sub('.*:(.*),.*','\\1',x))
      )
      ## Unit: milliseconds
      ##                            expr         min         lq     median             uq        max neval
      ## gagolews-stri_extract_all_regex    4.722515   4.811009   4.835948       4.883854   6.080912   100
      ##        gagolews-str_extract_all  103.514964 103.824223 104.387175     106.246773 117.279208   100
      ##          thelatemail-regmatches   36.049106  36.172549  36.342945      36.967325  47.399339   100
      ##                  agstudy-lapply   21.152761  21.500726  21.792979      22.809145  37.273120   100
      ##                 agstudy-lapply2    8.763783   8.854666   8.930955       9.128782  10.302468   100
      

      如您所见,基于stringi 的解决方案是最快的。

      【讨论】:

      • 谢谢! +10 这个绝妙的答案!
      • 您可以从 gsubfn 包中添加 strapply 函数作为另一个选项。
      • @gagolews 你是stringi 包的作者吗?良好的自动促销:)
      • 没想到会这么快 ;)
      • 在您解释之前,我从不理解前瞻/后置正则表达式。很简单,但我显然想多了。
      【解决方案3】:

      不使用正则表达式的另一种选择:

      unlist(lapply(unlist(strsplit(line,',')),function(x)unlist(strsplit(x,':'))[2]))
      
      "city1-street1-long1-lat1" 
      "city2-street2-long2-lat2" 
      "city3-street3-long3-lat3"
      "city3-street3-long3-lat3"
       NA   
      

      编辑更好的解决方案

      使用strssplitsub 的组合。无需设置确切的复杂结构,只需使用 grouping 功能:

      lapply(strsplit(line,'//'),function(x) sub('.*:(.*),.*','\\1',x))
      [[1]]
      [1] "city1-street1-long1-lat1" 
          "city2-street2-long2-lat2" 
          "city3-street3-long3-lat3" 
          "city3-street3-long3-lat3"
      

      【讨论】:

        【解决方案4】:

        对于像这样简单的事情,base R 处理得很好。

        matches <- regmatches(line, gregexpr('(?<=:).*?(?=,)', line, perl=T))
        

        【讨论】:

        • 感谢您的帮助。使用我的简化示例,这非常有效。但是在实际情况下,我需要提取所有介于 '{\"name\":\' 和 '\"}' 之间的字符串。希望您(或其他人)能建议如何执行此任务。
        • @user3638423 你能提供一个示例输入行吗?
        • 这是一条很长的行(这就是我简化示例的原因)。要获取数据,您可以运行以下代码: www_SB schoonenberg.nl/winkels/') line
        • 好的,例如,{"name":"Schoonenberg Hoorcomfort","url":"\/winkels\/schoonenberg-hoorcomfort-aalsmeer-zijdstraat-17-a","longitude":4.7467513,"latitude":52.2691185,"features":[],"id":"392858746"} 你想从中得到什么?
        • (?&lt;="name":).*?(?=,"features")
        猜你喜欢
        • 2021-01-09
        • 1970-01-01
        • 2020-09-23
        • 1970-01-01
        • 2014-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多