【问题标题】:Extract data from a list and get it into a tidy tibble, R从列表中提取数据并将其放入一个整洁的小标题中,R
【发布时间】:2023-03-20 15:20:01
【问题描述】:

我有一个列表(代码示例中的列表)我希望循环并从中提取数据并进入一个整洁的数据集(代码示例中的目标 tibble)。该列表由 5 个元素组成,每个元素代表申请表中的一个页面。每个元素都是一个字符串。

  1. 我希望从第一个元素中提取与数字和组织相关的信息。

  2. 在 Start(element 3) 和 stop(element 5) 这两个词之间,我的目标是提取与 name 和 info 相关的信息。这是名称和信息之后的冒号(:) 和我希望提取的换行符之间的信息。也许正则表达式解决方案是可能的?在代码示例中,有 3 个名称和 3 个信息。我努力构建一个通用函数,可以在定义的边界(开始、停止)内处理任意数量的名称和信息。

如何在 R 中解决这个问题?感谢任何帮助。我使用 str_extract_all() 进行了一些尝试,但都失败了。

library(tidyverse)

target <- tibble(number = c("10", "10", "10"),
          organization = c("TEST", "TEST", "TEST"),
       name = c("X", "Y", "Z"),
       info = c(12, 1, 43))

string1 <- "Application \r\n Date: 2020-09-23\r\n number: 10\r\n organization: TEST \r\nMail: x@x.com\r\n
             Page 1(5)\r\n"
string2 <- "Application \r\n Date: 2020-09-23\r\n ZZZZZZZZ\r\n
             Page 2(5)\r\n"
string3 <- "Application \r\n Date: 2020-09-23\r\n Start\r\n name: X\r\ninfo: 12\r\nmiss: NO\r\nname: Y\r\ninfo: 1\r\nname: Z\r\
             Page 3(5)\r\n"
string4 <- "Application \r\n Date: 2020-09-23\r\n info: 43\r\n miss: YES\r\nPage 4(5)\r\n"
string5 <- "stop\r\nname: ZY\r\ninfo:45\r\nMISS:-\r\nPage 5(5)"

list <- as.list(c(string1, string2, string3, string4, string5))

【问题讨论】:

  • 你确定你的“目标”匹配输入数据,应该有 5 行?
  • 是的。我的目标是为每个名称(X、Y、Z)设置一行。而且我只想从开始停止边界的名称中提取数据。这是一个尝试重现我真实案例的条件,即从大型申请表(pdf)中提取数据。
  • 我明白了,您是否尝试过使用tabulizer,用于从 PDF 中提取表格。
  • 没有。我使用来自 pdftools 的 pdf_text()。该函数为 pdf 中的每一页返回一个带有换行符的长字符串。也许制表机更好?它需要安装 Java,当我使用我的工作计算机时,这对我来说是个问题。

标签: r list loops


【解决方案1】:

我想这就是你想要实现的目标:

str <- paste0(string1, string2, string3, string4, string5)
str_extract_all(str, regex("(?<=start).+?(?=stop)", dotall = TRUE,ignore_case = TRUE))[[1]] -> strs

str_match_all(strs, regex("name: *([^\\r\\n]+?)\\r\\n.*?info: *([^\\r\\n]+?)\\r\\n", dotall=T))[[1]][,-1] -> mat

tibble(name=mat[,1], info=mat[,2], number=as.numeric(str_extract(str, "(?<=number: )\\d+")),organization=str_extract(str, "(?<=organization: ).+(?= +\\r)") )
# A tibble: 3 x 4
  name  info  number organization
  <chr> <chr>  <dbl> <chr>       
1 X     12        10 TEST        
2 Y     1         10 TEST        
3 Z     43        10 TEST  

说明:

我正在使用前瞻 (?=pat)(resp.lookbehinds (?&lt;=pat))检查以下(resp.previous)字符是否与 pat 匹配。

  • str_extract_all(..., "(?&lt;=start).+?(?=stop)") 获取 start 和 stop 之间的文本。
  • name: *([^\\r\\n]+?)\\r\\n.*?info: *([^\\r\\n]+?)\\r\\n
    1. name: * 匹配 name: 后跟任意数量的空格。
    2. ([^\\r\\n]+?) 捕获一个或多个不同于回车符\r 和换行符\r 的字符,? 量词将匹配可能的最小字符数,即在正则表达式中使+ 量词不贪心。
    3. \\r\\n.*? 匹配文字 \r\n.*? 尽可能少的任意字符数。
    4. ([^\\r\\n]+?)\\r\\n 捕获 .... 然后匹配文字 \r\n

【讨论】:

  • 我真的很感激。我没有掌握所有的正则表达式。我当然会更深入地研究它,但如果这对你来说不是太麻烦的话,你会指导我了解发生了什么吗?你为什么把它做成一个字符串而不是一个列表?在这种情况下,字符串有什么优势吗?
  • @Henrik 我添加了解释并简化了代码。我把它变成了一个字符串,这样我就可以得到开始和停止之间的数据,因为第三个名字在另一个页面上有它的信息。以这种方式操作字符串更容易。另外,如果您在一个文件中有多个开始和停止,我可以适应。
  • 我想我遵循正则表达式。乐趣!我当然遇到了一个新问题,因为我需要将我的真实数据放入一个字符串中,就像您使用的那样。 Pdf_text 返回一个列表,每页一个字符串。一个元素是整个页面。
  • 如果它返回一个列表,您可以使用unlist(ur.lst)将其转换为向量
  • paste0(ur.lst, collapse="") 使其成为一个字符串
猜你喜欢
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多