【问题标题】:pandas extract() returns empty dataframepandas extract() 返回空数据框
【发布时间】:2021-10-20 03:48:48
【问题描述】:

你能帮我一下吗?

我有一个数据帧 split() [我相信它是一个数据帧,其中每一行都是一个列表?] 的结果如下:

0 [001, 2491010000, Blah, 99, Blah, Blah, 2,57]
1 [01.01.20, 0048000002, 21.02.20, #176627, #176627, 001, 2491010000, Blah, 89, Blah, 70.418,60]
2 [01.01.20, Blah, 21.02.20, #176627, 001, 2491010000, Blah, 89, Blah, 3.258,67]

我想迭代上面的内容并创建一个像这样的新数据框:

Code         Code1     Price
2491010000   99        2,57
2491010000   89        70.418,60
2491010000   89        3.258,67

我用的是sn-p:

t = journal.str.extract(r'00\d\D{2}(\d{10})\D+(\d{2})\D+(\d+[,.]\d+[,.]\d+)',)
t

但 t 返回为空。我在the regex simulator 中测试了正则表达式,似乎工作正常,所以我怀疑问题出在输入'journal' 上。

你能告诉我正确的方法吗?谢谢!

【问题讨论】:

  • 试试df[['Code', 'Code1', 'Price']] = df['journal'].str.extract(r'00\d\D*(\d{10})\D*(\d{2})\D*(\d+(?:[,.]\d+)+)', expand=True)
  • 我认为问题仍然存在,因为 journal 是在连接两个拆分后创建的 dtype('O')。不过我会保留更复杂的正则表达式!

标签: python regex pandas extract


【解决方案1】:

如果框架不是太大并且要保持正则表达式更小,您可以尝试:

import pandas as pd
import re

'''
"[001, 2491010000, Blah, 99, Blah, Blah, 2,57]"
"[01.01.20, 0048000002, 21.02.20, #176627, #176627, 001, 2491010000, Blah, 89, Blah, 70.418,60]"
"[01.01.20, Blah, 21.02.20, #176627, 001, 2491010000, Blah, 89, Blah, 3.258,67]"
'''

df = pd.read_csv('df_strings.csv', header=None)

print(df, '\n')

                                                   0
0      [001, 2491010000, Blah, 99, Blah, Blah, 2,57]
1  [01.01.20, 0048000002, 21.02.20, #176627, #176...
2  [01.01.20, Blah, 21.02.20, #176627, 001, 24910... 


def getValues(x):
    code = re.search(r'(\d{10})', x).group(1)
    code1 = re.search(r'\s(\d{2}),', x).group(1)
    price = re.search(r'(\d+,\d+)', x).group(1)
    price = price.replace(',', '.')
    return pd.Series([code, code1, price])

df[['code', 'code1', 'price']] = df.apply(lambda x: getValues(x[0]), axis=1)

print(df[['code', 'code1', 'price']])

         code code1   price
0  2491010000    99    2.57
1  0048000002    89  418.60
2  2491010000    89  258.67

【讨论】:

    【解决方案2】:

    您的正则表达式与数据不匹配。我发现了 2 个问题:

    • \d+[,.]\d+[,.]\d+ 总是想要 2 个逗号或点,但你的第一行只有 1 个逗号和 0 个点
    • 00\d\D{2}(\d{10}) 预计 3 位数字和 10 位数字之间有 2 个非数字分隔符,但可能只有一个或超过 2 个(我不知道,因为我的问题中只有拆分数据,不是原始数据)。

    我将价格匹配正则表达式更改为(\d{,3}(?:\.\d{3})*,\d+),如果您不总是希望小数点后有数字,您也可以使用(\d{,3}(?:\.\d{3})*(?:,\d+)?)

    • ?: 标记非捕获组,因此它们不会被提取返回
    • 将千位分隔符与下一个数字放在一起可以知道它们总是有 3 个,并且这个 4 个字符的块可以根据需要重复多次。

    我还将00\d 更改为\d{10} 分隔符为\s+,这意味着任意数量的空白字符。以分词标记 \b 开始正则表达式还可以确保 00\d 本身是一个词,而不是另一个数字的结尾。

    >>> journal.str.extract(r'\b00\d\s+(\d{10})\D+(\d{2})\D+(\d{,3}(?:\.\d{3})*,\d+)')
                0   1          2
    0  2491010000  99       2,57
    1  2491010000  89  70.418,60
    2  2491010000  89   3.258,67
    

    您可以直接在正则表达式中命名您的捕获组:

    >>> journal.str.extract(r'\b00\d\s+(?P<Code>\d{10})\D+(?P<Code1>\d{2})\D+(?P<Price>\d{,3}(?:\.\d{3})*,\d+)')
             Code Code1      Price
    0  2491010000    99       2,57
    1  2491010000    89  70.418,60
    2  2491010000    89   3.258,67
    

    这可以帮助读者弄清楚每个捕获块的作用,但也会增加混乱。看个人喜好。

    【讨论】:

    • 请不要省略0 min 限制量词值,正则表达式的最佳做法是始终使用它。
    • 如果省略 0,它在某些正则表达式风格中不起作用(有时,它使正则表达式无效,有时,返回意外匹配,因为它被正则表达式库错误解析)。这样更安全保留它。
    猜你喜欢
    • 2021-08-23
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    相关资源
    最近更新 更多