R-匹配多个字符串,同时排除意外的匹配

时间:2019-03-29 01:46:39

标签: r regex

我正在从数据框中的混乱字符列中提取重量(克和公斤)和体积(毫升和公升)值,但无法排除总重量和体积。

一些示例数据如下:

df <-
rbind(data.frame(text = "199-50 150g4_qty_+ 200g4_qty_"),
      data.frame(text = "chouffe/ 330ml*2_qty_+ 330ml*2_qty_+ 330ml*2_qty_"),
      data.frame(text = "1000g( 500g+ 500g) _qty_"),
      data.frame(text = "(abbott) 900g+50g 2 950g"),
      data.frame(text = "1kg 2kg 3kg 1kg +2kg"),
      data.frame(text = "200ml*18_qty_ +putzi 50ml"),
      data.frame(text = "( 250ml*6_qty_+ 250ml*4_qty_+ 190ml*6_qty_+ 200ml*4_qty_)"),
      data.frame(text = "128g+ 128g+ 128g 384g"))

通过对该站点的跟踪并经过反复试验,我编写了提取所需值以及一些我不想要的值的代码。

df1 <- regmatches(df$text, gregexpr("\\d+(ml|l|g|kg)", df$text))
df1 <- as.data.frame(t(sapply(df1, '[', seq(max(sapply(df1, length))))))  

我得到:

    V1       V2       V3        V4      V5
1   150g     200g     NA        NA      NA
2   330ml    330ml    330ml     NA      NA
3   1000g    500g     500g      NA      NA
4   900g     50g      950g      NA      NA
5   1kg      2kg      3kg       1kg     2kg
6   200ml    50ml     NA        NA      NA
7   250ml    250ml    190ml     200ml   NA
8   128g     128g     128g      384g    NA 

大部分存在,但我想排除多余的值,例如重复(第5行)和总计(第3、4和8行)。最终结果应该是:

    V1       V2       V3        V4      
1   150g     200g     NA        NA      
2   330ml    330ml    330ml     NA     
3   500g     500g     NA        NA      
4   900g     50g      NA        NA
5   1kg      2kg      NA        NA
6   200ml    50ml     NA        NA      
7   250ml    250ml    190ml     200ml   
8   128g     128g     128g      NA

我已经确定,要保留的值之间必须立即有一个+。例如,第3行在500g和500g之间有一个+,所以我想保留这两个值,但我不想保留1000g,因为在这和500g之间没有+。同样,第8行384g之前也没有+

我只是不知道如何使用正则表达式来实现这一点,而又不能从太远的地方拿起+

1 个答案:

答案 0 :(得分:1)

从多个角度看待这个问题后,我的解决方案是删除加号周围的空白:

df$text <- gsub("\\s+(?=\\+)|(?<=\\+)\\s+", "", df$text, perl=TRUE)

然后根据剩余空间将字符串拆分为元素:

var1 <- strsplit(df$text, "\\s+")

然后使用grepl选择包含加号的元素,从而删除不包含+的所有元素:

var2 <- lapply(var1, function(x) x[grepl("\\+", x, perl=TRUE)])

最后使用先前创建的代码来保留所需的字符串:

df1 <- regmatches(var2, gregexpr("\\d+(ml|l|g|kg)", var2))
df1 <- as.data.frame(t(sapply(df1, '[', seq(max(sapply(df1, length)))))) 

这使我非常接近,可能需要对边缘进行一些修补,以处理异常情况。