【问题标题】:Extract Volume information from pandas series - Pandas , Regex从 pandas 系列中提取卷信息 - Pandas , Regex
【发布时间】:2020-07-17 08:30:50
【问题描述】:

我有一个熊猫系列,可以通过以下代码制作:


输入:

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)

问题陈述和预期输出:

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

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 

请建议我应该在这里做什么。

【问题讨论】:

    标签: python regex pandas


    【解决方案1】:

    你可以使用

    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
    

    【讨论】:

    • 嗨 Wiktor,如果系列中的最后一个字符串是 24X27.5cl 并且没有空格而不是 24 X 27.5cl,那么我应该将X? 之类的东西放在哪里?
    • @Ritz 所以,你不想在单词边界匹配,你只需要匹配前面没有数字的匹配,使用(?i)(?<!\d)(\d+(?:\.\d+)?)\s*(cl|ml|ltr|L)\b,见demo。跨度>
    • 你是个巫师。谢谢?
    【解决方案2】:

    最好使用 named 捕获组,这样结果 列具有有意义的名称。

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

    所以把你的代码改成:

    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$) 中的$ 是错误的,因为至少在 在一种情况下,您在测量单位之后有额外的文字。

    【讨论】:

      猜你喜欢
      • 2021-07-04
      • 2023-01-17
      • 2015-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      • 2018-10-12
      相关资源
      最近更新 更多