如何使用levenshtein功能在熊猫中降低相似的值

时间:2018-12-07 07:26:31

标签: python pandas dataframe pandas-groupby

我有一个看起来像-

的数据框
   ML_ENTITY_NAME        EDT_ENTITY_NAME
1  ABC BANK              HABIB METROPOLITAN BANK
2  ABC BANK              HABIB METROPOLITIAN BANK
3  BANK OF AMERICA       HSBC BANK MALAYSIA BHD
4  BANK OF AMERICA       HSBC BANK MALAYSIA SDN BHD
5  BANK OF NEW ZEALAND   HUA NAN COMMERCIAL BANK
6  BANK OF NEW ZEALAND   HUA NAN COMMERCIAL BANK LTD
7  CITIBANK N.A.         CHINA GUANGFA BANK CO LTD
8  CITIBANK N.A.         CHINA GUANGFA BANK CO.,LTD
9  SECURITY BANK CORP.   SECURITY BANK CORP
10 SIAM COMMERCIAL BANK  THE SIAM COMMERCIAL BANK PCL
11 TEMU                  ANZ BANK SAMOA LTD

我写了一个levenshtein函数,看起来就像-

def fm(s1, s2):
    score = Levenshtein.distance(s1,s2)
    if score == 0.0:
        score = 1.0
    else:
        score = 1 - (score / len(s1))
    return score

我想编写一个代码,如果两个EDT_ENTITY_NAME值的levenstein得分为greater than .75,那么我们将删除长度较小的一个值,并保留长度较大的一个。同样,{{1 }},以便进行比较。

我的最终输出应类似于-

ML_ENTITY_NAME

目前,我的方法是对df进行排序并在循环中进行迭代,并检查ML_ENTITY_NAME的值是否相同,然后计算EDT_ENTITY_NAME的levenshtein。我已经添加了一个新的列删除,并且如果满足上述条件并且一个ML_ENTITY_NAME的长度小于其他ML_ENTITY_NAME的长度,我会将Delete列更新为1。

我的代码如下-

   ML_ENTITY_NAME        EDT_ENTITY_NAME
1  ABC BANK              HABIB METROPOLITIAN BANK
2  BANK OF AMERICA       HSBC BANK MALAYSIA SDN BHD
3  BANK OF NEW ZEALAND   HUA NAN COMMERCIAL BANK LTD
4  CITIBANK N.A.         CHINA GUANGFA BANK CO.,LTD
5  SECURITY BANK CORP.   SECURITY BANK CORP
6  SIAM COMMERCIAL BANK  THE SIAM COMMERCIAL BANK PCL
7  TEMU                  ANZ BANK SAMOA LTD

当前它给出了错误的输出。

有人可以帮我一些答案/提示/建议吗?

2 个答案:

答案 0 :(得分:0)

我相信您需要:

#cross join by ML_ENTITY_NAME column
df1 = df.merge(df, on='ML_ENTITY_NAME', how='outer')
#remove same values per rows (distance 1)
df1 = df1[df1['EDT_ENTITY_NAME_x'] != df1['EDT_ENTITY_NAME_y']]
#apply function and compare
m1 = df1.apply(lambda x: fm(x['EDT_ENTITY_NAME_x'], x['EDT_ENTITY_NAME_y']), axis=1) > .75
m2 = df1['EDT_ENTITY_NAME_x'].str.len() > df1['EDT_ENTITY_NAME_y'].str.len()

#filtering
df2 = df1.loc[m1 & m2, ['ML_ENTITY_NAME','EDT_ENTITY_NAME_x']]
#remove  `_x`
df2.columns = df2.columns.str.replace('_x$', '')
#add unique rows per ML_ENTITY_NAME
df2 = df2.append(df[~df['ML_ENTITY_NAME'].duplicated(keep=False)]).reset_index(drop=True)
print (df2)
         ML_ENTITY_NAME               EDT_ENTITY_NAME
0              ABC BANK      HABIB METROPOLITIAN BANK
1       BANK OF AMERICA    HSBC BANK MALAYSIA SDN BHD
2   BANK OF NEW ZEALAND   HUA NAN COMMERCIAL BANK LTD
3         CITIBANK N.A.    CHINA GUANGFA BANK CO.,LTD
4   SECURITY BANK CORP.            SECURITY BANK CORP
5  SIAM COMMERCIAL BANK  THE SIAM COMMERCIAL BANK PCL
6                  TEMU            ANZ BANK SAMOA LTD

答案 1 :(得分:0)

您能指出您得到的输出到底有什么问题吗?我在代码中看到的唯一偏离目标的地方是,对于具有 0.74 的行对,您仅将delete标志设置为1,而应该而不是 0.75

请注意,在代码中排序是多余的,因为最终无论如何都要比较每对可能的行。实现排序时,您可能要想到的是遍历每对连续行,这会将代码的复杂度从O(n 2 )提升到O(n n)。

另一点说明是,您在if函数中不需要fm语句:语句score = 1 - score / len(s1)将涵盖这两种情况。