Как мне нечётко сопоставлять элементы в столбце массива в python?

У меня есть массив имен команд из NCAA, а также статистика, связанная с ними. Названия школ часто сокращаются или опускаются полностью, но обычно во всех вариациях названия есть общий элемент (например, Alabama Crimson Tide против Crimson Tide). Все эти имена содержатся в массиве в произвольном порядке. Я хотел бы иметь возможность взять все варианты названия команды путем нечеткого сопоставления их и переименовать все варианты в одно имя. Я работаю в Python 2.7, и у меня есть массив данных со всеми данными. Буду признателен за любую помощь, так как я никогда раньше не использовал нечеткое сопоставление.

Я рассмотрел нечеткое сопоставление через цикл for, который (несмотря на то, что он невероятно медленный) сравнивает каждый элемент в столбце массива с любым другим элементом, но я не совсем уверен, как его построить.

В настоящее время мой массив выглядит так:

{Имена, информация1, информация2, информация 3}

Длина массива составляет несколько тысяч строк, поэтому я стараюсь сделать программу максимально эффективной.

1 ответ

Расстояние редактирования Левенштейна является наиболее распространенным способом нечеткого сопоставления строк. Он доступен в пакете python-Levenshtein. Другое популярное расстояние - расстояние Яро Винклера, также доступное в том же пакете.

Предполагая простой массив numpy массив:

import numpy as np
import Levenshtein as lv

ar = np.array([
      'string'
    , 'stum'
    , 'Such'
    , 'Say'
    , 'nay'
    , 'powder'
    , 'hiden'
    , 'parrot'
    , 'ming'
    ])

Мы определяем помощников, чтобы дать нам индексы расстояний Левенштейна и Яро, между строкой, которую мы имеем, и всеми строками в массиве.

def levenshtein(dist, string):
    return map(lambda x: x<dist, map(lambda x: lv.distance(string, x), ar))

def jaro(dist, string):
    return map(lambda x: x<dist, map(lambda x: lv.jaro_winkler(string, x), ar))

Теперь обратите внимание, что расстояние Левенштейна является целочисленным значением, подсчитанным в количестве символов, в то время как расстояние Яро является значением с плавающей запятой, которое обычно изменяется от 0 до 1. Давайте проверим это, используя np.where:

print ar[np.where(levenshtein(3, 'str'))]
print ar[np.where(levenshtein(5, 'str'))]
print ar[np.where(jaro(0.00000001, 'str'))]
print ar[np.where(jaro(0.9, 'str'))]

И мы получаем:

['stum']
['string' 'stum' 'Such' 'Say' 'nay' 'ming']
['Such' 'Say' 'nay' 'powder' 'hiden' 'ming']
['string' 'stum' 'Such' 'Say' 'nay' 'powder' 'hiden' 'parrot' 'ming']
Другие вопросы по тегам