繁体   English   中英

如何使用R从一行中提取多个字符串

[英]How do I extract multiple character strings from one line using R

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

假设我有以下文本行(使用'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

我希望有人可以给我一个如何执行此任务的提示。

与救援相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"

使用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"

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

一些基准:

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的解决方案是最快的。

不使用正则表达式的另一个选项

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组合。 无需设置确切复杂的结构,只需使用分组功能:

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"

对于像这样简单的东西,基地R处理这个很好。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM