Попробуйте это:
По сути, мы перебираем каждую строку в каждой группе и вычисляем сходство, используя SequenceMatcher между значением этой строки и всеми другими строками в этой группе и присваивая максимальное значение новой колонка - здесь это достигается двумя лямбда-функциями - одна для внешней l oop, а другая для внутренней l oop
df = pd.DataFrame([['a', 1, 'str1'],
['a', 1, 'st2'],
['a', 1, 'str3'],
['a', 1, 'str10'],
['a', 2, 'str4'],
['a', 2, 'str5'],
['a', 2, 'str6']],
columns=['product', 'city', 'value'])
def func(grp):
def match(id, val):
matches = grp.drop(id).apply(lambda x: difflib.SequenceMatcher(None, x['value'], val).ratio(), axis=1)
return max([x for i, x in enumerate(matches) if x])
return grp.apply(lambda row: match(row.name, row['value']), axis=1)
res = df.groupby(['product', 'city']).apply(func).reset_index()
res['level_2'] = df['value']
res.rename(columns={'level_2':'value'}, inplace=True)
print(res)
Вывод:
product city value 0
0 a 1 str1 0.888889
1 a 1 st2 0.571429
2 a 1 str3 0.750000
3 a 1 str10 0.888889
4 a 2 str4 0.750000
5 a 2 str5 0.750000
6 a 2 str6 0.750000