【问题标题】:Exact pattern match in unstructered dataset (text or CSV file)非结构化数据集中的精确模式匹配(文本或 CSV 文件)
【发布时间】:2014-10-25 15:12:10
【问题描述】:

我需要找出将 CSV 或文本文件中的符号、字母和数字的精确模式组合与非常非结构化的数据集进行匹配的最佳方法。

我需要准确地提取模式“BR1*********”(BR1 + 正好 9 位),它位于行 :61: 的中间​​,以及模式“?54***”(?54 + 正好 3数字),它总是在行的末尾:61:。

这两种模式都是重复的,但数字组合不同。

到目前为止,我已经尝试过 grepgrepl 没有成功。结果,我总是收到整行,其中该模式近似匹配,但符号和数字不完全匹配。

以下是数据集的一小部分:

:11:hgttu6576575?//80&&80980jhkhkhlkhkh  gjdggfjsdf?kjhkuhsfk778798978**&
:27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
:61:kjljlkfjsdlBR1678899458iyuyugug7787?>?///uhhiuyi
jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54160
:11:hgggdgf79878yiuhlkhkh  gjdggfhuihiuhuiou89 ioiojsdf?kjhkuhsfk778798978**&
:27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
:61:kjljlkfjsdlBR1234885765iyuyugug7787?>?///uhhiuyi
jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54190

【问题讨论】:

  • 你能显示dput(head(lines))吗?此外,您能否检查该解决方案是否适用于较小的数据集子集? IE。 lines1 <- head(lines,20)
  • 嗨@akrun,感谢您提出这个问题。问题是它是一个包含数千行/行的巨大文件(File.txt),我无法使用行
  • 我不是在谈论发布完整文件。您可以使用lines <- readLines("file.txt") 读取文件,然后使用dput(head(lines)) 发布前几行。还让您在数据集的子集上运行代码。

标签: regex r grepl


【解决方案1】:

gsubfn 包中的strapplyc 可用于提取这些部分。在这里,我们提取整个字符串,或者如果您只想要数字部分在数字部分周围放置括号,例如pat1 <- "BR(1\\d{9})"

library(gsubfn)

pat1 <- "BR1\\d{9}"
pat2 <- "[?]54\\d{3}$"

strapplyc(lines, pat1, simplify = c)
## [1] "BR1678899458" "BR1234885765"

strapplyc(lines, pat2, simplify = c)
## [1] "?54160" "?54190"

或两者兼而有之:

strapplyc(lines, paste(pat1, pat2, sep = "|"), simplify = c)
## [1] "BR1678899458" "?54160"       "BR1234885765" "?54190"  

如果您想要行号(即第一行是 1,第二行是 2,等等)而不是值本身,请使用具有相同模式的 grep

添加如果文件只有几千行,读取文件应该没有问题:

lines <- readLines("File.txt")

如果它真的太大,你可以在 sqldf 包中读取 use read.csv.sql ,它在一行代码中可以读取 setup 一个 sqlite 数据库将文件读入其中,然后将一部分行提取到 R 中。这里我们有假设文件中没有?,但如果有则使用其他分隔符 不在文件中:

library(sqldf)

lines <- read.csv.sql("File.txt", header = FALSE, sep = "?", 
      sql = "select * from file where V1 like '%BR1%' or V1 like '%54%'")
# now use strapplyc as above

【讨论】:

  • 嗨@G.Grothendieck,感谢您分享您的解决方案。问题是它是一个包含数千行/行的巨大文件(File.txt),我无法使用行
  • 查看答案末尾添加的讨论。
  • 嗨@G.Grothendieck,非常感谢您分享此内容以及您的努力!从其他角度看待任务非常有帮助和有用。谢谢!
【解决方案2】:
dat <- readLines(textConnection(":11:hgttu6576575?//80&&80980jhkhkhlkhkh  gjdggfjsdf?kjhkuhsfk778798978**&
:27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
:61:kjljlkfjsdlBR1678899458iyuyugug7787?>?///uhhiuyi
jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54160
:11:hgggdgf79878yiuhlkhkh  gjdggfhuihiuhuiou89 ioiojsdf?kjhkuhsfk778798978**&
:27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
:61:kjljlkfjsdlBR1234885765iyuyugug7787?>?///uhhiuyi
jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54190"))

library(stringr)

unlist(str_match_all(dat, "(BR1[[:digit:]]{9})|(\\?54[[:digit:]]{3})"))
##  [1] "BR1678899458" "BR1678899458" ""             "?54160"      
##  [5] ""             "?54160"       "BR1234885765" "BR1234885765"
##  [9] ""             "?54190"       ""             "?54190"

如果我们对您需要的格式有更多了解,我们可以为您提供更好的帮助。

【讨论】:

  • 您好,感谢您的努力并分享您的解决方案。是的,您完全正确,格式非常重要(我忘了提及,抱歉)。问题是它是一个巨大的文件(File.txt),我不能使用 dat=readLines(textConnection("")。所以我尝试了:dat
  • 嗨@hrbrmstr,我用整个文件“File.txt”检查了你的代码,它工作正常。我意识到以前我使用了错误的文件。因为我需要同时匹配两种模式,所以最好的解决方案是:lines unlist(regmatches(lines, gregexpr('BR1\\d{9}|\\?54\ \d{3}', 行))) [1] "BR1678899458" "?54160" "BR1234885765" "?54190" "BR1548812358" "?54195" "BR1768834128" "?54199"
【解决方案3】:

您可以使用基础 R 处理这些匹配项的提取。

> unlist(regmatches(lines, gregexpr('BR1\\d{9}|\\?54\\d{3}', lines)))
# [1] "BR1678899458" "?54160"       "BR1234885765" "?54190" 

【讨论】:

  • 很快就开始称你为“医生”
  • @hwnd。就是这个!那成功了! :) 感谢一百万的分享。行 unlist(regmatches(lines, gregexpr('BR1\\d{9}|\\?54\\d{3}', lines))) [1] "BR1678899458 " "?54160" "BR1234885765" "?54190" "BR1548812358" "?54195" "BR1768834128" "?54199"
【解决方案4】:

我对自然语言描述的阅读是只有 2 行满足要求。例如,第 4 行确实有一个 "?54nnn$" 模式,但该行不以 ":61:" 开头:

dat=readLines(textConnection(":11:hgttu6576575?//80&&80980jhkhkhlkhkh  gjdggfjsdf?kjhkuhsfk778798978**&
:27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
:61:kjljlkfjsdlBR1678899458iyuyugug7787?>?///uhhiuyi
jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54160
:11:hgggdgf79878yiuhlkhkh  gjdggfhuihiuhuiou89 ioiojsdf?kjhkuhsfk778798978**&
:27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
:61:kjljlkfjsdlBR1234885765iyuyugug7787?>?///uhhiuyi
jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54190"))

> grep("^:61:.+(BR1\\d{9}|[?]54\\d{3}$)", dat)
#[1] 3 7

修改测试用例,看看我的模式建议对于我认为的问题是否正确执行:

> dat=readLines(textConnection(":11:hgttu6576575?//80&&80980jhkhkhlkhkh  gjdggfjsdf?kjhkuhsfk778798978**&
+ :27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
+ :61:kjljlkfjsdlBR1678899458iyuyugug7787?>?///uhhiuyi
+ :61:jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54160
+ :11:hgggdgf79878yiuhlkhkh  gjdggfhuihiuhuiou89 ioiojsdf?kjhkuhsfk778798978**&
+ :27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
+ :61:kjljlkfjsdlBR1234885765iyuyugug7787?>?///uhhiuyi
+ jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54190")
+ )
> grep("^:61:.+(BR1\\d{9}|[?]54\\d{3}$)", dat)
[1] 3 4 7

【讨论】:

  • 我从您的个人资料页面读到了这个Learned R on my own。你看过哪本书?
  • 我的第一本书是“S 中的现代应用统计学(第 2 版)?我可能应该选择一本很好的介绍性文本,但当时并没有真正的。在那之后我学会了通过阅读 Rhelp 邮件列表中的帖子,然后尝试回答它们,如果我不能,则运行其他贡献者的代码并逐行分解,阅读帮助页面并运行示例。
  • 由其他贡献者运行代码并逐行拆分,阅读帮助页面并运行示例。 - 我完全同意。这就是我完成大部分 R 学习的方式
  • 您好,非常感谢您分享您的解决方案。问题是它是一个巨大的文件(File.txt)(我应该在一开始就提到这个)并且我不能使用 dat=readLines(textConnection("")。所以我尝试了:dat
  • 如果模式都在同一行,那么模式参数将通过在两个模式之间放置一个可变长度的任意匹配来形成:"^:61:.+BR1\\d{9}.+[?]54\\d{3}$"readlines() 函数可以接受文件名参数,因此除非文件大小以千兆字节为单位,否则不应成为障碍。
【解决方案5】:

试试

   library(stringr)
   unlist(str_extract_all(lines, "(BR1\\d{9})|(\\?54\\d{3})"))
   #[1] "BR1678899458" "?54160"        "BR1234885765" "?54190"   

更新

如果文件很大,可以使用stringi,这样会更快

  library(stringi)
  na.omit(unlist(stri_extract_all_regex(lines, "(BR1\\d{9})|(\\?54\\d{3})")))
  #[1] "BR1678899458" "?54160"       "BR1234885765" "?54190"     

数据

lines <- readLines(textConnection(':11:hgttu6576575?//80&&80980jhkhkhlkhkh  gjdggfjsdf?kjhkuhsfk778798978**&
 :27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
 :61:kjljlkfjsdlBR1678899458iyuyugug7787?>?///uhhiuyi jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54160
 :11:hgggdgf79878yiuhlkhkh  gjdggfhuihiuhuiou89 ioiojsdf?kjhkuhsfk778798978**&
 :27:jhkjhuiy867tjhfsh/.>?kjklh8ggdhkotrdkhofkhodkgj
 :61:kjljlkfjsdlBR1234885765iyuyugug7787?>?///uhhiuyi jhkhkjhiy878697y8hukjlu97 ??///khiuy8oujhuhijk?54190'))

【讨论】:

  • 您好,非常感谢您分享您的解决方案。结果看起来相当不错。问题是它是一个巨大的文件(File.txt)(我应该在开头提到这一点)并且我不能使用 dat=readLines(textConnection(""),因为 txt.file 中有数千行所以我试过了:lines
  • 非常感谢您分享两种代码替代方案。这就是诀窍:)。对不起,我意识到以前我使用了错误的文件,但现在它工作得很好。库(stringr) > unlist(str_extract_all(lines, "(BR1\\d{9})|(\\?54\\d{3})")) [1] "BR1678899458" "?54160" "BR1234885765" "?54190" "BR1548812358" "?54195" "BR1768834128" "?54199"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-10
  • 2019-08-22
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多