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
你能帮我一下吗?
我有数据框 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