В большинстве ответов используется apply()
, что, как известно, медленнее, чем решения для встроенных векторных функций.Я надеялся на использование .replace()
, что это будет быстро, так как это такая встроенная векторная функция.Ответ @ vlemaistre был единственным, который не использовал .apply()
, как мое решение здесь, которое вместо компиляции каждого подстановочного знака в регулярное выражение обрабатывает его как правую подстроку для использования логики: «Если server_hostname
заканчивается на wildcard
, то это совпадение ".До тех пор, пока я сортирую свои шаблоны по длине, это работает просто отлично.
Моя функция, которая делает это:
def match_to_whitelist(accepts_df, whitelist_df):
""" Adds `whitelists` column to accepts_df showing which (if any) whitelist entry it matches with """
accepts_df.loc[:, 'wildcards'] = None
for wildcard in whitelist_df['wildcards']:
accepts_df.loc[(accepts_df['wildcards'].isnull()) & (
accepts_df['server_hostname'].str.endswith(wildcard)), 'wildcards'] = wildcard
rows_matched = len(accepts_df['wildcards'].notnull())
matched {rows_matched}")
return accepts_df
Здесь accepts_df
похожа на B
до, а whitelist_df
похожа на A
и раньше, но с двумя отличиями:
- нет
regex
столбец - значения
wildcards
больше не имеют формат glob / regex (т. Е. "(. *) Microsoft.com" становится "microsoft.com)"
Для сравнения ответов на моем компьютере я буду использовать мой в качестве базового уровня, принимая 27 сек для обработки 100k accepts_df
строк с 400 whitelist_df
строками. Используя тот же набор данных, вотвремя для других решений (мне было лень: если они не выбежали за ворота, я не стал много отлаживать, чтобы узнать):
- @ vlemaistre - Понимание списка с векторными функциями: 193сек
- @ user214 - SequenceMatcher: 234сек
- @ aws_apprentice - Сравнить длины результатов поиска RE: 24сек
- @ fpersyn - первое совпадение (будет наилучшим совпадением, если отсортировано
A
): более 6 минут, так что выходите ... - @ Энди Хейден -
lastgroup
: не тестировал, потому что я не могу (быстро) построить длинную программу REчески. - @ capelastegui -
Series.str.match()
: Ошибка: «pandas.core.indexes.base.InvalidIndexError: Переиндексация действительна только для уникальных объектов индекса»
В конечном итоге, ни один из наших ответовскажем, как использовать .replace()
по желанию, поэтому пока я оставлю этот вопрос без ответа на несколько недель, если кто-то сможет дать ответ, чтобы лучше использовать .replace()
или хотя бы какое-нибудь другое быстрое векторное решение,До тех пор я буду придерживаться того, что имею, или, возможно, буду использовать aws_apprentice после проверки результатов.
РЕДАКТИРОВАТЬ Я улучшил свое сопоставление, добавив столбец «домен» к обоим DF, который состоит из двух последних частей каждого подстановочного знака / имени_хоста_сервера (т.е. www.microsoft.com становится "Microsoft".com ").Затем я использовал groupby('domain')
на обоих DF, итерировал по группам белых списков доменов, выбрал одну и ту же группу доменов из DF-сервера имя_сервера (B) и выполнил сопоставление, просто используя подмножество подстановочных знаков / имен_хостов из каждой группы.Это сократило мое время обработки до половины.