#python
#python
Вопрос:
У меня есть список названий продуктов, некоторые из которых являются избыточными или похожими:
List = ['CocaCola','CocaCola 3 Oz','Twix','Twix Caramel','Foldgers 3 Oz','Foldgers 10 Oz','Haagen Dazs Caramel','Black Forest Ham','Black Label Whiskey',...]
Я хотел бы написать функцию, которая группировала бы похожие названия продуктов, чтобы возвращать список:
NewList = ['CocaCola','Twix','Foldgers','Haagen Dazs Caramel','Black Forest Ham','Black Label Whiskey',...]
Я думал о сопоставлении подстрок, но это не сработало бы, поскольку «CocaCola 3 Oz» и «Foldgers 3 Oz» оба отображались бы на «3 унции».
Я также подумал только о первой подстроке в каждом названии продукта:
NewList = []
for w in List:
ws = w.split(' ')
NewList.append(ws[0])
Но это сопоставило бы ‘ветчину из Шварцвальда’ и ‘Виски Black Label’ с ‘Черным’.
Как я могу получить это сопоставление? Я знаю о beautifulsoup и подумал, что это может помочь, но я не смог найти ни одного сообщения, которое указывало бы на это.
Для уточнения на основе комментариев Брусуэйна: Я получаю список из Pandas df (не знаю, почему это актуально?). ‘CocaCola’ и ‘Pepsi’ будут сопоставлены с разными группами ‘CocaCola’ и ‘Pepsi’. ‘Ветчина из Шварцвальда’ и ‘Ветчина Оскара Мейера’ также были бы отнесены к разным группам, ‘CocaCola’ и ‘CocaCola Light’ были бы отнесены к одной и той же группе ‘CocaCola’. В основном я ищу группировку на основе названий брендов, а не категорий продуктов. Это то, что определяет сходство.
Я уже приводил пример того, как будет выглядеть результат на основе входных данных.
Я подумал, что beautifulsoup поможет, потому что это библиотека для обработки текста.
Комментарии:
1. Что определяет, похожи ли продукты?
Twix
иTwix Caramel
более очевидно, но хотели бы вы сгруппироватьCocaCola
иPepsi
вместе? Как насчетBlack Forest Ham
иOscar Meyer Ham
? Можете ли вы показать ожидаемый результат для включенных вами примеров? Чтоbeautifulsoup
имеет к этому отношение? Вы получаете этот список откуда-нибудь из Интернета или из XML-документа?2. Что касается вашей правки: как бы вы идентифицировали название бренда в строке?
3. @KlausD. в этом суть моего вопроса. Я не знаю всех названий брендов заранее, или я бы использовал какую-то таблицу поиска.
4. Итак, вы уже знаете ответ. То, что вы пытаетесь сделать, является частью обработки естественного языка и само по себе является сложной темой.
5. (Мои извинения, не понял, что второй список был ожидаемым результатом.)
Ответ №1:
Вы можете достичь того, что пытаетесь сделать, используя алгоритмы кластеризации в вашем наборе данных.
a = ['CocaCola','CocaCola 3 Oz','Twix','Twix Caramel','Foldgers 3 Oz','Foldgers 10 Oz','Haagen Dazs Caramel','Black Forest Ham','Black Label Whiskey']
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import KMeans
cv=CountVectorizer()
vect=cv.fit_transform(a)
km=KMeans(n_clusters=6)
km.fit_predict(vect)
ВЫХОДНОЙ СИГНАЛ:
array([0, 0, 1, 1, 2, 2, 4, 3, 5], dtype=int32)
Это говорит нам о том, что:
Кластер 0: «Кокакола», «КокаКола 3 унции»
Группа 1: «Твикс», «Твикс Карамельный»
Группа 2: «Формочки 3 унции», «Формочки 10 унций»
Группа 3: «Карамель Haagen Dazs»
Кластер 4: «Ветчина из Шварцвальда»
Группа 5: «Виски Black Label»
Сначала вы векторизуете свои данные, т.е. преобразуете каждый элемент в вашем списке в одномерный массив чисел. Здесь я использую CountVectorizer (его легко понять и он служит этой цели), но доступны и другие векторизаторы. Каждая цифра в массиве 1D будет представлять слово, а значение этой цифры будет представлять количество раз, когда оно встречается в этом тексте. Эта ссылка поможет вам лучше понять CountVectorizer, он же алгоритм набора слов.
Опять же, существует множество алгоритмов кластеризации на выбор, и я выбрал кластеризацию KMeans по той же причине, что и раньше, — ее легко понять и реализовать.Это поможет вам понять кластеризацию KMeans.
Примечание: Вам нужно указать количество кластеров, которое вам требуется, как указано в km=KMeans(n_clusters=6)
. Изменение значения здесь может изменить ваши результаты. Например,
Если km=KMeans(n_clusters=5)
, то «Ветчина Шварцвальд» и «Виски Black Label» будут отнесены к одной категории в одном кластере.
Я надеюсь, что это поможет вам.
Ответ №2:
Вы могли бы использовать регулярное выражение, чтобы выделить только ту часть имени, которая стоит перед числом.
products = ['CocaCola','CocaCola 3 Oz','Twix','Twix Caramel','Foldgers 3 Oz','Foldgers 10 Oz','Haagen Dazs Caramel','Black Forest Ham','Black Label Whiskey']
import re
products = list(set(re.findall("(.*?)[0-9]",name "0")[0].strip() for name in products))
print(products)
# ['Black Label Whiskey', 'CocaCola', 'Black Forest Ham', 'Twix Caramel', 'Twix', 'Haagen Dazs Caramel', 'Foldgers']