2017-01-04 86 views
1

我有50000個獨特行和20列下面大熊貓數據幀(包括是相關列的一個片段):搜索一個Python的數據幀/字典模糊匹配在另一個數據幀

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" 

我也有其具有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" 

我所想要做的是在DF2比較「PRODUCT_DESCRIPTION」字段DF1到了「PROD_DESCRIPTION」現場,並找到最接近的匹配/匹配,以幫助繁重的一部分。然後,我需要手動檢查比賽結果,但速度會更快。理想的結果將如下所示。與一個或多個部分匹配記錄:

 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中的產品ID都是唯一的,因此保留索引並不重要。結果也可以保存到一個新的數據框中,因爲這將被應用到約有1400萬行的第三個數據框。

我用以下問題及答案(其中包括):

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,熊貓已經fuzzywuzzy安裝。

回答

2

,計算我的距離矩陣這樣

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.ratio,fuzz.partial_ratio等),以便我可以看到哪個結果最好。感謝你對我的論文的重視。 – gincard

+1

只需添加 - fuzz.token_sort_ratio產生最準確的結果,約70%的成功匹配。 – gincard

+0

@gincard多少數據和它的速度是多少......大概 – piRSquared

0

您應該能夠遍歷兩種dataframes和填充或者是第3數據幀的字典與你想要的信息:使用fuzz.ratio我的距離度量

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) 
相關問題