【问题标题】:Extracting relevant information from text in R - regex从 R 中的文本中提取相关信息 - 正则表达式
【发布时间】:2018-05-10 11:06:05
【问题描述】:

我正在尝试从文本文档中提取一些信息。我已使用pdftext(). 将此文本文档转换为数据框现在我想提取我所追求的信息。下面是创建像我这样的数据框的代码:

text <- data.frame(page = c(1,1,2,3), sen = c(1,2,1,1), text = c("Dear Mr case 1","the value of my property is £500,000.00 and it was built in 1980", 
                                                             "The protected percentage is 0% for 2 years", "The interest rate is fixed for 2 years at 4.8%"))

从上面的数据框中,我需要提取以下内容:

1:人的性别。在这种情况下,它将是男性(看着先生)

2:代表属性值的数字。在这种情况下为 500,000.00 英镑。

3:受保护的百分比值,在我们的例子中为 0%。

4:利率值,在我们的例子中是 4.8%。

理想情况下,我想输出如下数据框:

即使我可以单独提取这些信息,它仍然足够好。我可能可以使用正则表达式,告诉它​​找到像“受保护的百分比”这样的模式,然后给我在它找到这个模式后立即出现的数字。任何帮助将不胜感激。

【问题讨论】:

  • 你是对的,正则表达式可以工作,但如果你的文本变化很大,那么它就会失败。我建议您查看自然语言处理 (NLP) 包,例如 koRpus,以获得更好的文本挖掘。
  • 数据结构的标准化程度如何?例如,是否总是每人四个字符串?周围的文字总是一样的吗?如果是这样,在这种情况下,一些正则表达式将是微不足道的。
  • 结构总是与周围的文本相同。人名的长度并不总是相同,但总体而言,其他所有内容的格式都一致。

标签: r regex text-mining information-extraction


【解决方案1】:

假设您可以将 R 数组的所有部分放入一个字符串中,这个正则表达式就可以完成这项工作(将其设置为不区分大小写):

dear\s+(mr|mrs|miss|ms)\b[^£]+(£[\d,.]+)(?:\D|\d(?![\d.]*%))+([\d.]+%)(?:\D|\d(?![\d.]*%))+([\d.]+%)

匹配位于捕获组 1、2、3 和 4。

这是一个演示(查看右侧的匹配窗格): https://regex101.com/r/OcVN5r/1

我不太了解 R,但我知道您可以执行以下操作:

regmatches(subject, 
gregexpr("dear\\s+(mr|mrs|miss|ms)\\b[^£]+(£[\\d,.]+)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)",
subject, perl=TRUE, ignore.case=TRUE));

但我将 R 的详细信息留给你。

编辑:也许这适用于 R:

matches <- gregexpr("dear\\s+(mr|mrs|miss|ms)\\b[^£]+(£[\\d,.]+)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)", subject, perl=TRUE, ignore.case=TRUE);
result <- lapply(matches, function(m) attr(m, "capture.start")[,1])
for (i in seq_along(result))
  attr(result[[i]], "match.length") <- attr(matches[[i]], "capture.length")[,1]
result

【讨论】:

  • 谢谢@Jaifroid。我查看了您的正则表达式,在演示中它似乎工作正常。在 R 上试过没有用。我还尝试在与您相同的网页上打开一个新会话并复制和粘贴您的正则表达式以及文本。当我尝试打开一个新会话时,它在网站上也不起作用。
  • 我正在考虑将整个正则表达式分成多个步骤,然后组合它们的输出。例如。首先获取先生或小姐信息,然后获取“受保护百分比”之后出现的数字
  • 查看您的 regex101,问题仅仅是因为您没有将 regex 设置为不区分大小写。单击顶部正则表达式右侧出现的小“gm”,然后选择不区分大小写。使用 R,您是否使用了我上面建议的 ignore.case=TRUE 选项?编辑:如果你确定你总是让 Mr Mrs Miss Ms 用正确的大写字母拼写,你可以使正则表达式区分大小写。在这种情况下,只需更改正则表达式中的那些以使用初始资本。还将dear 更改为Dear
  • 我知道,如果您在 R:gregexpr("dear\\s+(mr|mrs|miss|ms)\\b[^£]+(£[\\d,.]+)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)(?:\\D|\\d(?![\\d.]*%))+([\\d.]+%)", subject, perl=TRUE, ignore.case=TRUE); 中执行此操作,那么您将获得一个列表,其中包含每个元素中所有正则表达式匹配的位置和长度的向量。但我真的不知道 R。
  • 我在答案中添加了更多模板代码,以便您查看是否可以调整。
【解决方案2】:

这是一个部分解决方案:您要提取的每个块的正则表达式。您可能需要调整正则表达式或如何将事物放在数据框中,但这应该可以帮助您。请注意 R 包 stringr 使用 ICU regex,并且需要使用双反斜杠进行转义。

p_load(tidyverse)

ttt <- str_flatten(text$text)

# gender
gender_regex <- c("M.s*")
gender <- str_match(ttt, gender_regex) 

.:任何字符(即MrMrsr,或Mss
*:重复s 0次或更多次, 尽可能多(即 1 个来自 Mrss 或 2 个来自 Miss 的)

# number property value
propval_regex <- regex("\U00A3\\d\\S++\\s")
property_value <- str_match(ttt, propval_regex) %>%
  str_trim()

\U00A3:英镑符号的 unicode hex
\\d:任何数字
\\S:任何非空白字符(即包括千位和小数分隔符)
++:匹配1次或多次
\\s : 空白字符

# protected percentage value and interest rate
# regex for all percentages
r <- "\\d++\\.?+\\d?+\\%"

# vector of matches
percents <- str_match_all(ttt, r) %>%
  flatten_chr()

# each as its own variable
protected_percentage_value <- percents[1]
interest_rate <- percents[2]

\\d:任意数字
++:重复 1 次或多次
\\.:小数分隔符
?+:重复 0 次或一次
\\%:百分号

【讨论】:

    猜你喜欢
    • 2015-03-18
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    相关资源
    最近更新 更多