我有一个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% 70cl
,1942 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
请在这里建议我该怎么做。
答案 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)
-cl
,ml
,ltr
或L
(注意区分大小写的匹配)\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 $)中的$
是错误的,因为至少在
在一种情况下,在计量单位之后还有其他文字。