从熊猫系列中提取体积信息-熊猫,正则表达式

时间:2020-04-05 10:32:55

标签: python regex pandas

我有一个Pandas系列,可以通过以下代码生成:


输入:

l = ['abcd 1942 Lmauu 40% 70cl',
    'something again something   1.5 L',
    'some other stuff 45% 70 CL',
    'not the exact data      3LTR',
    'abcd 100Ltud 6%(8)500ML',
    'cdef  6%(8)500 ml',
    'a packet 24 x 27.5 cl (  PET )']
ser = pd.Series(l)

问题说明和预期输出:

我正在尝试从系列中提取卷并将其转换为数据框,以使该卷位于数据框的一列中,而度量单位位于另一列中,可以使用以下代码重现预期的输出:

d = {0: {0: '70',
     1: '1.5',
     2: '70',
     3: '3',
     4: '500',
     5: '500',
     6: '27.5'},
     1: {0: 'cl', 1: 'L', 2: 'CL', 3: 'LTR', 4: 'ML', 5: 'ml', 6: 'cl'}}
expected_output = pd.DataFrame(d)

      0    1
0    70   cl
1   1.5    L
2    70   CL
3     3  LTR
4   500   ML
5   500   ml
6  27.5   cl 

我的尝试代码

这是我尝试过的,我已经很接近我想要的了,但是不太接近,如果您看到我没有得到最后一卷。我想是因为我在正则表达式中包含了$,但是如果没有它,我将无法解析该卷,例如abcd 1942 Lmauu 40% 70cl1942 L将会被返回。另外,我只希望第二列中的度量单位而不是输出中所示的第一列,而是第二列。

print(ser.str.extract(r'((?i)([\d]+?[.])?\d+?[\s+]?(cl$|ml$|ltr$|L$)(?:$))').iloc[:,[0,-1]]) 

        0    2
0    70cl   cl
1   1.5 L    L
2   70 CL   CL
3    3LTR  LTR
4   500ML   ML
5  500 ml   ml
6     NaN  NaN 

请在这里建议我该怎么做。

2 个答案:

答案 0 :(得分:2)

您可以使用

r'(?i)\b(\d+(?:\.\d+)?)\s*(cl|ml|ltr|L)\b'

请参见regex demo

详细信息

  • (?i)-启用不区分大小写的模式
  • \b-单词边界
  • (\d+(?:\.\d+)?)-捕获组1:一个或多个数字,后跟一个可选的点和一个或多个数字序列
  • \s*-超过0个空格
  • (cl|ml|ltr|L)-clmlltrL(注意区分大小写的匹配)
  • \b-单词边界

测试:

>>> ser.str.extract(r'(?i)\b(\d+(?:\.\d+)?)\s*(cl|ml|ltr|L)\b', expand=True)
      0    1
0  70    cl 
1  1.5   L  
2  70    CL 
3  3     LTR
4  500   ML 
5  500   ml 
6  27.5  cl

答案 1 :(得分:1)

最好使用已命名捕获组,以便获得结果 列具有有意义的名称。

我还简化了您的正则表达式,并将度量单位更改为小写。

因此将代码更改为:

res = ser.str.extract(r'(?i)(?P<Amount>\d+(?:\.\d+)?)\s?(?P<Unit>[CM]?L|LTR)\b')
res.Unit = res.Unit.str.lower()

结果是:

  Amount Unit
0     70   cl
1    1.5    l
2     70   cl
3      3  ltr
4    500   ml
5    500   ml
6   27.5   cl

还请注意,(cl $ | ml $ | ltr $ | L $)中的$是错误的,因为至少在 在一种情况下,在计量单位之后还有其他文字。