#python #pandas #dataframe #recommendation-engine
Вопрос:
Я перепробовал все известные мне способы, чтобы проверить, похоже ли ключевое слово на что-то в названии моего фильма dataset.csv, но ничего не работает. Он рекомендует мне фильмы только в том случае, если название точно такое же, как в наборе данных. например: если бы я искал Человека-паука 3, то он порекомендовал бы мне фильмы, связанные с ним, но если бы я искал человека-паука 3, то он не знал бы, что я имел в виду, и показал бы ошибку.
import pandas as pd
import openpyxl
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizer
df = pd.read_csv('dataset.csv')
df.head(3)
df['Movie_id'] = range(0,1000)
#print(df.head(10))
#print(df.shape)
columns = ['Actors', 'Director', 'Genre', 'Title']
#print(df[columns].head(3))
#print(df[columns].isnull().values.any())
def important(data):
features = []
for i in range(0, data.shape[0]):
features.append(data['Actors'][i] ' ' data['Director'][i] ' ' data['Genre'][i] ' ' data['Title'][i])
return features
df['features'] = important(df)
#print(df.head(3))
cm = CountVectorizer().fit_transform(df['features'])
cs = cosine_similarity(cm)
print(cs)
print(cs.shape)
title = "Spider-Man 3"#works
#title = "spider man" doesnt works
movie_id = df[df.Title == title]['Movie_id'].values[0]
scores = list(enumerate(cs[movie_id]))
sorted_Scores = sorted(scores, key = lambda x:x[1], reverse=True)
sorted_Scores = sorted_Scores[1:]
print(sorted_Scores)
a = 0
print("The 10 most recommended movie to", title, 'are:')
for item in sorted_Scores:
movie_title = df[df.Movie_id == item[0]]['Title'].values[0]
print(a 1, movie_title)
a = 1
if a > 9:
break
итак, как я могу сделать его ключевым словом, основанным на этом коде.
Комментарии:
1. Нет необходимости заново изобретать колесо, функциональность полнотекстового поиска MySQL (FTS) может быть тем, что вам нужно. Дополнительная (более четкая) ссылка здесь.
Ответ №1:
Вы можете воспользоваться библиотекой fuzzywuzzy.
from fuzzywuzzy import process, fuzz
titles = df['Title'].unique().tolist()
fuzzy_matches = process.extract('Spider-Man 3', titles, scorer=fuzz.token_set_ratio)
После этого fuzzy_matches
должны содержаться кортежи с похожими словами и значением того, насколько они похожи. Затем вы можете выбрать наиболее подходящее название и выполнить его поиск.
Подобный этому:
best_fitting_title = fuzzy_matches[0][0]
movie_id = df[df.Title == best_fitting_title]['Movie_id'].values[0]
Я не тестировал его полностью, потому что у меня нет образцов данных, но он должен работать.
Ответ №2:
Ваша проблема здесь в том, что вы пытаетесь найти фильм по точному названию здесь:
movie_id = df[df.Title == title]['Movie_id'].values[0]
Там вы ищете df.Title == title
, и если есть какая-то разница в названиях, она ничего не находит.
Ваше решение состоит в том, чтобы использовать какой-то алгоритм подобия строк, чтобы найти наиболее похожий существующий заголовок на ваше ключевое слово. Вот минимальный рабочий пример использования встроенного python SequenceMatcher
для поиска идентификатора фильма с наиболее похожим названием на ваше ключевое слово.
from difflib import SequenceMatcher
from functools import partial
import pandas as pd
df = pd.DataFrame([{'Movie_id': 0, 'Title': 'Spider-Man 3'},
{'Movie_id': 1, 'Title': 'Iron-Man 3'},
{'Movie_id': 2, 'Title': 'Titanic'},
{'Movie_id': 3, 'Title': 'Iconic'}])
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
title = 'ironman 3'
most_similar_index = df[['Title']].apply(lambda row: similar(row['Title'], title), axis=1).argmax()
movie_id = df.loc[most_similar_index, 'Movie_id']
Выход:
print(movie_id)
1
Ответ №3:
Используйте fuzzywuzzy
пакет:
# Python env: pip install fuzzywuzzy
# Anaconda env: conda install fuzzywuzzy
from fuzzywuzzy import extractOne
>>> df
Movie_id Movies
0 11 Spider-Man
1 12 Superman
2 12 Batman
>>> title
'Spider 3'
>>> extractOne(title, df['Movies'])
('Spider-Man', 82, 0)
# (text, score, index)
>>> df.iloc[extractOne(title, df['Movies'], score_cutoff=80)[2]]['Movie_id']
11