SPEEDUP PANDAS СИНТАКСИЧЕСКИЙ АНАЛИЗ FINDALL DATE - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть эта серия

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 для этой серии, что является ожидаемым результатом.

running% 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 таким образом, я уверен, что мой код выбирает правильный месяц и может затем преобразовать его в datetim e.

Так в чем же проблема

, если я запускаю свой один вкладыш на 1 миллион записей и% времени, это то, что я получаю

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)

Так что, пожалуйста, я буду признателен, если кто-то может помочь в ускорении этого, а также оценят некоторые объяснения

1 Ответ

0 голосов
/ 09 апреля 2020

Я попробовал ваш процесс на vanilla python, используя модуль re, и он был значительно быстрее; Вы, вероятно, должны дать ему go. Я не думаю, что 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

...