Векторизация или ускорение нечеткого совпадения строк в столбце PANDAS - PullRequest
0 голосов
/ 03 октября 2018

Я пытаюсь найти потенциальные совпадения в столбце PANDAS, полном названий организаций.В настоящее время я использую iterrows (), но это очень медленно на фрейме данных с ~ 70000 строк.После просмотра StackOverflow я попытался реализовать лямбда-метод row (apply), но это, кажется, едва ускоряет процесс, если вообще делает.

Первые четыре строки кадра данных выглядят следующим образом:

index  org_name
0   cliftonlarsonallen llp minneapolis MN
1   loeb and troper llp newyork NY
2   dauby o'connor and zaleski llc carmel IN
3   wegner cpas llp madison WI

Следующий блок кода работает, но на его обработку ушло около пяти дней:

org_list = df['org_name']
from fuzzywuzzy import process
for index, row in df.iterrows():
    x = process.extract(row['org_name'], org_list, limit=2)[1]
    if x[1]>93:
        df.loc[index, 'fuzzy_match'] = x[0]
        df.loc[index, 'fuzzy_match_score'] = x[1]

Действуетдля каждой строки я сравниваю название организации со списком всех названий организаций, беру два верхних совпадения, затем выбираю второе наилучшее совпадение (потому что верхнее совпадение будет идентичным именем), а затем устанавливаю условие, чтооценка должна быть выше 93, чтобы создать новые столбцы.Причина, по которой я создаю дополнительные столбцы, заключается в том, что я не хочу просто заменять значения - я хотел бы сначала проверить результаты дважды.

Есть ли способ ускорить это?Я прочитал несколько постов в блоге и вопросы StackOverflow, в которых говорилось о «векторизации» этого кода, но мои попытки этого не увенчались успехом.Я также подумал о том, чтобы просто создать матрицу расстояний Левенштейна размером 70 000 x 70 000, а затем извлечь из нее информацию.Существует ли более быстрый способ создания наилучшего соответствия для каждого элемента в списке или столбце PANDAS?

1 Ответ

0 голосов
/ 03 октября 2018

Это решение использует apply() и должно демонстрировать разумные улучшения производительности.Не стесняйтесь поиграть с scorer и измените threshold в соответствии со своими потребностями:

import pandas as pd, numpy as np
from fuzzywuzzy import process, fuzz

df = pd.DataFrame([['cliftonlarsonallen llp minneapolis MN'],
        ['loeb and troper llp newyork NY'],
        ["dauby o'connor and zaleski llc carmel IN"],
        ['wegner cpas llp madison WI']],
        columns=['org_name'])

org_list = df['org_name']

threshold = 40

def find_match(x):

  match = process.extract(x, org_list, limit=2, scorer=fuzz.partial_token_sort_ratio)[1]
  match = match if match[1]>threshold else np.nan
  return match

df['match found'] = df['org_name'].apply(find_match)

Возвраты:

                                   org_name                                     match found
0     cliftonlarsonallen llp minneapolis MN             (wegner cpas llp madison WI, 50, 3)
1            loeb and troper llp newyork NY             (wegner cpas llp madison WI, 46, 3)
2  dauby o'connor and zaleski llc carmel IN                                             NaN
3                wegner cpas llp madison WI  (cliftonlarsonallen llp minneapolis MN, 50, 0)

Если вы просто хотите вернуть соответствующийСама строка, затем вы можете изменить ее следующим образом:

match = match[0] if match[1]>threshold else np.nan

Я добавил комментарий @ user3483203, относящийся к пониманию списка, в качестве альтернативы:

df['match found'] = [find_match(row) for row in df['org_name']]

Обратите внимание, чтоprocess.extract() предназначен для обработки одной строки запроса и применения переданного алгоритма оценки к этому запросу и предоставленным параметрам соответствия.По этой причине вам нужно будет сравнить этот запрос со всеми 70000 вариантов совпадения (так, как вы сейчас настраиваете код).Поэтому вы будете оценивать len(match_options)**2 (или 4 900 000 000) сравнений строк.Поэтому я думаю, что наилучшего улучшения производительности можно достичь, ограничив потенциальные параметры сопоставления с помощью более обширной логики в функции find_match(), например, установив, что параметры сопоставления начинаются с той же буквы, что и запрос, и т. Д.

...