pandas 提取() returns 空数据框

pandas extract() returns empty dataframe

你能帮我一下吗?

我有数据框 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

我使用了代码段:

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

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

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

您的正则表达式与数据不匹配。我发现了 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+)?)

  • ?:标记非捕获组,这样它们就不会被extract返回
  • 将千位分隔符与下一个数字放在一起可以知道它们总是有 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

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

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

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