#python-3.x #string #levenshtein-distance
#python-3.x #строка #левенштейн-расстояние
Вопрос:
Я работаю над стандартизацией некоторых данных, которые я получаю через футбольный API.
У меня есть функция с тремя входными данными, home
, away
(две футбольные команды) и списком строк, которые содержат команду home
или away
, но они могут называться иначе, чем входные home
и away
.
Моя цель — заменить все экземпляры home
в списке на 1, а все экземпляры away
в списке на 2.
Вот несколько примеров входных данных:
home: "Manchester United", away: "Liverpool", list = ["Man Utd and Yes", "Liverpool and No", "Man Utd and No", "Liverpool and Yes"]
home: "Manchester United", away: "Manchester City", list = ["Man Utd and Yes", "Man City and No", "Man Utd and No", "Man City and Yes"]
home: "Paris Saint Germain", away: "Monaco", list = ["Monaco and Yes", "Monaco and No", "PSG and Yes", "PSG and No"]
home: "Brighton amp; Hove Albion", away: "Chelsea", list = ["Chelsea and No", "Brighton and Yes", "Chelsea and Yes", "Brighton and No"]
Обратите внимание, названия команд в списке совпадают (вы никогда не увидите «Манчестер Юнайтед» и «Да», «Манчестер Юнайтед» и «Нет» в одном списке).
Теперь, как мне сопоставить команды? Это то, что я делал до сих пор:
def standardise(home, away, lst):
for i, v in enumerate(lst):
team = v.split("and")[0]
if team in home or home in team:
lst[i] = v.replace(team, "1")
for j, k in enumerate(lst):
new_team = k.split("and")[0]
if new_team != i and team != new_team:
lst[j] = k.replace(new_team, "2")
else:
lst[j] = k.replace(new_team, "1")
elif team in away or away in team:
# same code as above but for away
elif enchant.utils.levenshtein(team, home) >=
enchant.utils.levenshtein(team, away):
lst[i] = v.replace(team, "2")
else:
lst[i] = v.replace(team, "1")
Где расстояние Левенштейна измеряет минимальное количество правок, которые вам нужно сделать, чтобы заменить последовательность из одного слова на другую.
Теперь этот метод не работает в 100% случаев, например, с акронимами, метод, похоже, дает сбой.
Есть ли лучший способ сделать это, возможно, более конкретный метод, который кто-нибудь может придумать?
Ответ №1:
Fuzzywuzzy идеально подходит для этого. довольно просто документы тоже
from fuzzywuzzy import process
def standardise(home, away, lst):
home_away = {home:'1', away:'2'}
choices = [home, away]
print ([ home_away[process.extractOne(each, choices)[0]] for each in lst ])
home = "Manchester United"
away = "Liverpool",
lst = ["Man Utd and Yes", "Liverpool and No", "Man Utd and No", "Liverpool and Yes"]
standardise(home, away, lst)
home = "Manchester United"
away = "Manchester City"
lst = ["Man Utd and Yes", "Man City and No", "Man Utd and No", "Man City and Yes"]
standardise(home, away, lst)
home = "Paris Saint Germain"
away = "Monaco"
lst = ["Monaco and Yes", "Monaco and No", "PSG and Yes", "PSG and No"]
standardise(home, away, lst)
home = "Brighton amp; Hove Albion"
away = "Chelsea"
lst = ["Chelsea and No", "Brighton and Yes", "Chelsea and Yes", "Brighton and No"]
standardise(home, away, lst)
Вывод:
['1', '2', '1', '2']
['1', '2', '1', '2']
['2', '2', '1', '1']
['2', '1', '2', '1']
Ответ №2:
Вы можете попробовать сначала убрать гласные, чтобы каждое название было ближе к его аббревиатуре, а затем применить Levenshtein.
И также проверьте fuzzywuzzy.