使用正则表达式提取混合分数和可能也包含带R(stringr)的混合分数的文本

Use regex to extract mixed fraction and text that may also contain mixed fractions with R (stringr)

请查看下面我正在处理的数据示例,但是我总共有 100K+ 个条目。

注意UNIT下评论里的...只是为了凑合。例如,完整的 UNIT 文本是第一项是 4- to 5-mm-diameter,第五项是 3 1/2- to 4-inch-diameter,等等

library(tidyverse)
                                                #i QTY    UNIT
parts <- c("6 4- to 5-mm-diameter plugs",       #1  6     4- to...diameter
           "6 large bricks",                    #2  6     large
           "1 1/3 shipment concrete",           #3  1.33  shipment
           "1 (14- to 15-oz) gold bars",        #4  1     (14- to 15-oz)
           "16 3 1/2- to 4-inch-diameter caps", #5  16    3 1/2- to...eter
           "1 1/2 tons sand",                   #6  1.5   tons
           "2 1 1/4- to 3-inch diameter caps",  #7  2     1 1/4- to...eter      
           "1/3 shipment cement")               #8  .333  shipment 

我从 SO 上的一些答案中取得了一些成功,但是当 UNIT 文本 also 包含混合时,我 运行 遇到了问题第 1 项和第 5 项中的分数:

# Goal: extract QTY as mixed frac
parts %>% 
  str_extract("(\d+[\/\d[ ]?]*|\d*)")

# i=1, 5 broken
#[1] "6 4"      "6 "       "1 1/3 "   "1 "       "16 3 1/2" "1 1/2 "  

# Goal: extract UNIT word
parts %>% 
  str_extract("[[:graph:]]{3,11}|[- to ].{5,21}")

# all i with some problem  
# [1] " 4- to 5-mm-diameter p" " large bricks"          " 1/3 shipment concrete"
# [4] " (14- to 15-oz) gold b" " 3 1/2- to 4-inch-diam" " 1/2 tons sand"

我的目标是提取 QTYUNIT,如代码注释中所示,从第一个条目到最后一个条目为 6, 6, 1 1/3, 1, 16, 1, 2, 1/3 - 此外,我正在尝试提取UNIT 下的文本被缩写为适合代码部分 - 这里是完整的:4- to 5-mm-diameter, large, shipment, (14- to 15-oz), 3 1/2- to 4-inch-diameter, tons, 1 1/4- to 3-inch diameter, shipment.

我的直觉建议我应该分两步完成此操作,但请告诉我是否有更好的方法来实现此目的。

谢谢。

编辑:添加了一个关键示例 8。

您可以使用

m <- str_match(parts, '^(\d+(?:\s+\d+/\d+)?|\d+/\d+)\s+((?:\d+(?:-?in(?:ch)?|")?\s+)*\S+(?:\s+to\s+(?:\d+(?:-?in(?:ch)?|")?\s+)*\S+)?)')
qty <- m[,2]
# => [1] "6"     "6"     "1 1/3" "1"     "16"    "1 1/2" "2"     "1/3"  
unit <- m[,3]
# => [1] "4- to 5-mm-diameter"       "large"                    
#    [3] "shipment"                  "(14- to 15-oz)"           
#    [5] "3 1/2- to 4-inch-diameter" "tons"                     
#    [7] "1 1/4- to 3-inch diameter" "shipment"      

参见R demo and the regex demo详情:

  • ^ - 字符串开头
  • (\d+(?:\s+\d+/\d+)?|\d+/\d+) - 第 1 组 (m[,2]):一个或多个数字后跟可选的一个或多个空格、一个或多个数字、/ 和一个或多个数字,或用一位或多位数字括起的 /
  • \s+ - 一个或多个空格
  • ((?:\d+(?:-?in(?:ch)?|")?\s+)*\S+(?:\s+to\s+(?:\d+(?:-?in(?:ch)?|")?\s+)*\S+)?) - 第 2 组 (m[,3]):
    • (?:\d+(?:-?in(?:ch)?|")?\s+)* - 一个或多个数字出现零次或多次,后跟可选的 " 或可选的 -in,然后是可选的ch 子字符串,然后是一个或多个空格
    • \S+ - 一个或多个除空格以外的字符(“单词”)
    • (?:\s+to\s+(?:\d+(?:-?in(?:ch)?|")?\s+)*\S+)? - 可选出现:
      • \s+to\s+ - to 包含一个或多个空格
      • (?:\d+(?:-?in(?:ch)?|")?\s+)* - 见上文
      • \S+ - 除空格外的一个或多个字符。