2017-01-04 11 views
1

У меня есть следующие панды dataframe с 50000 уникальных строк и 20 столбцов (входит отрывок из соответствующих столбцов):Поиск один Python dataframe/словарь для нечетких совпадений в другой dataframe

df1:

  PRODUCT_ID   PRODUCT_DESCRIPTION 
0   165985858958   "Fish Burger with Lettuce" 
1   185965653252   "Chicken Salad with Dressing" 
2   165958565556   "Pork and Honey Rissoles" 
3   655262522233   "Cheese, Ham and Tomato Sandwich" 
4   857485966653   "Coleslaw with Yoghurt Dressing" 
5   524156285551   "Lemon and Raspberry Cheesecake" 

Я также иметь следующий dataframe (который я и сохраненную в виде словаря), который имеет 2 колонки и 20000 уникальных строк:

df2 (также сохранен как ди ct_2)

 PROD_ID PROD_DESCRIPTION 
0  548576 "Fish Burger" 
1  156956 "Chckn Salad w/Ranch Dressing" 
2  257848 "Rissoles - Lamb & Rosemary" 
3  298770 "Lemn C-cake" 
4  651452 "Potato Salad with Bacon" 
5  100256 "Cheese Cake - Lemon Raspberry Coulis" 

То, что я хочу сделать, это сравнить поле «PRODUCT_DESCRIPTION» в df1 в поле «PROD_DESCRIPTION» в df2 и найти ближайший матч/матчи, чтобы помочь с тяжелой подъемной части. Затем мне нужно было бы вручную проверить совпадения, но было бы намного быстрее. Идеальный результат будет выглядеть так, например. с одним или несколькими указанными совпадениями:

 PRODUCT_ID  PRODUCT_DESCRIPTION    PROD_ID PROD_DESCRIPTION 
0 165985858958 "Fish Burger with Lettuce"  548576 "Fish Burger" 
1 185965653252 "Chicken Salad with Dressing"  156956 "Chckn Salad w/Ranch Dressing" 
2 165958565556 "Pork and Honey Rissoles"   257848 "Rissoles - Lamb & Rosemary"  
3 655262522233 "Cheese, Ham and Tomato Sandwich" NaN  NaN 
4 857485966653 "Coleslaw with Yoghurt Dressing" NaN  NaN 
5 524156285551 "Lemon and Raspberry Cheesecake" 298770 "Lemn C-cake" 
6 524156285551 "Lemon and Raspberry Cheesecake" 100256 "Cheese Cake - Lemon Raspberry Coulis" 

Я уже завершил соединение, которое определило точные соответствия. Не важно, что индекс сохраняется, так как идентификаторы продукта в каждом df уникальны. Результаты также могут быть сохранены в новый фреймворк данных, так как это будет применено к третьему фреймворку данных, который содержит около 14 миллионов строк.

Я использовал следующие вопросы и ответы (среди прочих):

Is it possible to do fuzzy match merge with python pandas
Fuzzy merge match with duplicates включая модуль пытается медузы, как это предлагается в одном из ответов
Python fuzzy matching fuzzywuzzy keep only the best match
Fuzzy match items in a column of an array

, а также различные петли/функции/отображение и т. д., но не имели успеха, либо получив первый «нечеткий матч», который имеет низкий балл, либо не обнаружено совпадений.

Мне нравится идея создания столбца сопоставления/расстояния, создаваемого согласно here, поскольку это позволило бы мне ускорить процесс ручной проверки.

Я использую Python 2.7, pandas и установлен fuzzywuzzy.

ответ

2

используя fuzz.ratio как мой показатель расстояния, вычислить мою матрицу расстояний, как это

df3 = pd.DataFrame(index=df.index, columns=df2.index) 

for i in df3.index: 
    for j in df3.columns: 
     vi = df.get_value(i, 'PRODUCT_DESCRIPTION') 
     vj = df2.get_value(j, 'PROD_DESCRIPTION') 
     df3.set_value(
      i, j, fuzz.ratio(vi, vj)) 

print(df3) 

    0 1 2 3 4 5 
0 63 15 24 23 34 27 
1 26 84 19 21 52 32 
2 18 31 33 12 35 34 
3 10 31 35 10 41 42 
4 29 52 32 10 42 12 
5 15 28 21 49 8 55 

Установите пороговое значение для допустимого расстояния. Я установил 50
Найти значение индекса (для df2), которое имеет максимальное значение для каждой строки.

threshold = df3.max(1) > 50 
idxmax = df3.idxmax(1) 

назначать задания

df['PROD_ID'] = np.where(threshold, df2.loc[idxmax, 'PROD_ID'].values, np.nan) 
df['PROD_DESCRIPTION'] = np.where(threshold, df2.loc[idxmax, 'PROD_DESCRIPTION'].values, np.nan) 
df 

enter image description here

+0

Я использовал это на небольшом подмножестве данных и, похоже, это хорошо работает. Я просто установил его для работы над большим блоком с четырьмя различными итерациями для тестирования различных способов использования fuzz (т. Е. Fuzz.ratio, fuzz.partial_ratio и т. Д.), Чтобы я мог видеть, что дает наилучшие результаты. Цените свою помощь с тяжелым подъемом моей диссертации. – gincard

+1

Просто для добавления - fuzz.token_sort_ratio произвел самый точный результат с примерно 70% успешными матчами. – gincard

+0

@ gincard Сколько данных и как быстро это было ... приблизительно – piRSquared

0

Вы должны быть в состоянии перебрать как dataframes и заполнить либо Dict из 3-го dataframe с нужной информацией:

d = { 
    'df1_id': [], 
    'df1_prod_desc': [], 
    'df2_id': [], 
    'df2_prod_desc': [], 
    'fuzzywuzzy_sim': [] 
} 
for _, df1_row in df1.iterrows(): 
    for _, df2_row in df2.iterrows(): 
     d['df1_id'] = df1_row['PRODUCT_ID'] 
     ... 
df3 = pd.DataFrame.from_dict(d)