0

我有这个系列

df = pd.Series(['01/January/2021', '09/Sept/2021', 'November/11/2022', '02/02/2016', '2021/01/August', '2022-Feb-02'])

提取我申请的 3 个字母

df.str.upper().str.findall(r'[a-zA-Z]{3}')

这给出了一个输出

['JAN', 'UAR'], ['SEP'], ['NOV', 'EMB'], [], ['AUG', 'UST'], ['FEB']

运行 %timeit

In [22]: %timeit df.str.upper().str.findall(r'[a-zA-Z]{3}')                                                                                 
447 µs ± 3.08 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

为了获得我必须做的第一个分组

df.str.upper().str.findall(r'[a-zA-Z]{3}.str[0]')

导致

['JAN', 'SEP', 'NOV', nan, 'AUG', 'FEB']

再次运行 %timeit 结果到

In [23]: %timeit df.str.upper().str.findall(r'[a-zA-Z]{3}').str[0]                                                                          
710 µs ± 13.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我也有月份的清单

_calc = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']

我的最后一行代码现在是

df.str.upper().str.findall(r'[a-zA-Z]{3}').str[0].isin(_calc).all()

这给出了这个系列的 False,这是预期的结果。

运行 %timeit 最终给出

In [25]: %timeit df.str.upper().str.findall(r'[a-zA-Z]{3}').str[0].isin(_calc).all()                                                       
932 µs ± 16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我为什么要这样做:我正在从 csv 文件中读取日期,随着时间的推移,我发现日期格式是一个非常大的问题,因为这取决于用户区域日期格式,因此确定哪个月份可能是一个问题,因此,如果月份的格式为 %b 或 %B,那么我确信我的代码选择了正确的月份,然后可以将其转换为日期时间。

那么问题出在哪里?如果我针对 100 万个条目运行我的一个班轮并且 %timeit 这就是我得到的

In [28]: %timeit qf.date.str.upper().str.findall(r'[a-zA-Z]{3}').str[0].isin(_calc).all()                                           
1.6 s ± 11.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

我怎样才能加快速度,减速发生在哪里?

4

1 回答 1

0

我在 vanilla Python 中尝试了你的过程,使用“re”模块,它明显更快;你可能应该试一试。与数字相比,我不认为 Pandas 字符串方法针对速度进行了优化。

此外,@cs95 的这篇文章可能会更深入地了解 Pandas 中的字符串操作。

import re
pattern = re.compile(r'[a-zA-Z]{3}')
pat = [pattern.search(entry) for entry in df.tolist() ]
pat = [entry.group().upper() if entry  else None for entry in pat]
res = set(pat)<=set(_calc)

如果您只想找出搜索结果中是否有 None ,您可以使用内置的all函数:

 pat = all(pattern.search(entry) for entry in df.tolist() )

您可以使用 if 语句重新调整它。

于 2020-04-09T09:14:54.383 回答