Если вы установите fuzzywuzzy
, у вас все еще остается проблема, как выбрать правильную эвристику, чтобы выбрать правильный продукт и вырезать те продукты, которые выбраны неправильно (объяснение ниже)
установка fuzzywuzzy
:
pip install fuzzywuzzy
fuzzywuzzy
имеет несколько методов для вычисления коэффициента ( примеры на github ). Вы сталкиваетесь с проблемой: как выбрать лучшее? Я попробовал их на ваших данных, но все они потерпели неудачу.
Код:
import pandas as pd
import numpy as np
from fuzzywuzzy import fuzz
# df1 = ...
# df2 = ...
def get_top_by_ratio(x, df2):
product_values = df2.Product.values
# compare two strings by characters
ratio = np.array([fuzz.partial_ratio(x, val) for val in product_values])
argmax = np.argmax(ratio)
rating = ratio[argmax]
linked_product = product_values[argmax]
return rating, linked_product
Примените эту функцию к вашим данным:
partial_ratio = (df1.Brand_var.apply(lambda x: get_top_by_ratio(x, df2))
.apply(pd.Series) # convert returned Series of tuples into pd.DataFrame
.rename(columns={0: 'ratio', 1: 'Product'})) # just rename columns
print(partial_ratio)
Out:
0 65 1960 Altmeister 330ML CAN METAL # Altmeister Bitter
1 50 test # Altos Las Hormigas Argentinian Wine
2 33 test
3 50 test
4 50 test
Это не хорошо. Другие методы отношения, такие как fuzz.ratio
, fuzz.token_sort_ratio
и т. Д., Тоже потерпели неудачу.
Так что, полагаю, расширить эвристику для сравнения слов могут не только символы. Определите функцию, которая будет создавать словарь из ваших данных, кодировать все предложения и использовать более сложный эвристический поиск слов:
def create_vocab(df1, df2):
# Leave 0 index free for unknow words
all_words = set((df1.Brand_var.str.cat(sep=' ') + df2.Product.str.cat(sep=' ')).split())
vocab = dict([(i + 1, w) for i, w in enumerate(all_words)])
return vocab
def encode(string, vocab):
"""This function encodes a sting with vocabulary"""
return [vocab[w] if w in vocab else 0 for w in string.split()]
Определить новую эвристику:
def get_top_with_heuristic(x, df2, vocab):
product_values = df2.Product.values
# compare two strings by characters
ratio_per_char = np.array([fuzz.partial_ratio(x, val) for val in product_values])
# compare two string by words
ratio_per_word = np.array([fuzz.partial_ratio(x, encode(val, vocab)) for val in product_values])
ratio = ratio_per_char + ratio_per_word
argmax = np.argmax(ratio)
rating = ratio[argmax]
linked_product = product_values[argmax]
return rating, linked_product
Создание словарного запаса, применение сложной эвристики к данным:
vocab = create_vocab(df1, df2)
heuristic_rating = (df1.Brand_var.apply(lambda x: get_top_with_heuristic(x, df2, vocab))
.apply(pd.Series)
.rename(columns={0: 'ratio', 1: 'Product'}))
print(heuristic_rating)
Out:
ratio Product
0 73 1960 Altmeister 330ML CAN METAL # Altmeister Bitter
1 61 Hormi 12 Yr Bottle # Altos Las Hormigas Argentinian Wine
2 45 Hormi 12 Yr Bottle
3 50 test
4 50 test
Кажется, это правильно! Конкатенируйте этот фрейм данных в df1, измените индекс:
result_heuristic = pd.concat((df1, heuristic_rating), axis=1).set_index('Brand_var')
print(result_heuristic)
Out:
ratio Product
Brand_var
Altmeister Bitter 73 1960 Altmeister 330ML CAN METAL
Altos Las Hormigas Argentinian Wine 61 Hormi 12 Yr Bottle
Amadeus Contri Sparkling Wine 45 Hormi 12 Yr Bottle
Amadeus Cream Liqueur 50 test
Amadeus Sparkling Sparkling Wine 50 test
Теперь вам нужно выбрать какое-то правило большого пальца, чтобы вырезать неверные данные. Для этого примера ratio <= 50
работает хорошо, но вам, вероятно, понадобятся некоторые исследования, чтобы определить лучший эвристический и правильный порог . Также вы все равно получите некоторые ошибки. Выберите приемлемый коэффициент ошибок, то есть 2%, 5% ... и улучшайте свой алгоритм, пока не достигнете его (эта задача аналогична проверке алгоритмов классификации машинного обучения).
Вырезать неверные "прогнозы":
result = result_heuristic[result_heuristic.ratio > 50][['Product']]
print(result)
Out: Product
Brand_var
Altmeister Bitter 1960 Altmeister 330ML CAN METAL
Altos Las Hormigas Argentinian Wine Hormi 12 Yr Bottle
Надеюсь, это поможет!
P.S. Конечно, этот алгоритм очень очень медленный, когда вы оптимизируете его, вы должны сделать некоторые оптимизации, например, кэшировать различия и т. Д.