使用模糊python去除重复的近似词匹配

Remove duplicate approximate word matching using fuzzy python

我想问一下如何在python或任何可行的方法中使用模糊删除重复的近似词匹配。我有一个excel包含近似相似的名字,此时,我想删除包含高相似性的名字,只保留一个名字。

比如这里是输入(excel文件),一共有6行5列:

|-------------------|-----|-----|-----|-----|-----|  
| abby_john         | abc | abc | abc | abc | abc |
|-------------------|-----|-----|-----|-----|-----|  
| abby_johnny       | def | def | def | def | def |  
|-------------------|-----|-----|-----|-----|-----|  
| a_j               | ghi | ghi | ghi | ghi | ghi |  
|-------------------|-----|-----|-----|-----|-----|  
| abby_(john)       | abc | abc | abc | abc | abc |  
|-------------------|-----|-----|-----|-----|-----|  
| john_abby_doe     | def | def | def | def | def | 
|-------------------|-----|-----|-----|-----|-----|  
| aby_/_John_Doedy  | ghi | ghi | ghi | ghi | ghi |  
|-------------------|-----|-----|-----|-----|-----|  

虽然上面所有的名字看起来都不一样,但实际上是一样的,python怎么知道它们都是一样的,去掉重复的名字,仍然是任何一个 的名字,仍然是整行?顺便说一句,输入文件是 Excel 文件格式 (.xlsx)。

期望的输出:

|-------------------|-----|-----|-----|-----|-----|  
| abby_john         | abc | abc | abc | abc | abc |
|-------------------|-----|-----|-----|-----|-----|  

由于下划线不是很重要,可以用'spacing'代替,因此可以接受如下的另一个输出: 另一个期望的输出:

|-------------------|-----|-----|-----|-----|-----|  
| abby_john         | abc | abc | abc | abc | abc |
|-------------------|-----|-----|-----|-----|-----|  

如果有人能帮助我,我将不胜感激,谢谢!

我使用此功能更正和替换名称,然后删除重复的匹配项,仅保留第一个匹配项

import difflib
import re

def similarity_replace(series):

    reverse_map = {}
    diz_map = {}
    for i,s in series.iteritems():
        diz_map[s] = re.sub(r'[^a-z]', '', s.lower())
        reverse_map[re.sub(r'[^a-z]', '', s.lower())] = s

    best_match = {}
    uni = list(set(diz_map.values()))
    for w in uni:
        best_match[w] = sorted(difflib.get_close_matches(w, uni, n=3, cutoff=0.5), key=len)[0]

    return series.map(diz_map).map(best_match).map(reverse_map)

df = pd.DataFrame({'name':['abby_john','abby_johnny','a_j','abby_(john)','john_abby_doe','aby_/_John_Doedy'],
                       'col1':['abc','add','sda','sas','sad','ass'],
                       'col2':['abc','add','sda','sas','sad','ass'],
                       'col3':['abc','add','sda','sas','sad','ass']})

df['name'] = similarity_replace(df.name)
df

df.drop_duplicates(['name'])

a_j 似乎无法删除

这是一个名为 semantic similarity 的 class 问题。

获取数据:

from io import StringIO
s = StringIO("""abby_john         abc   abc   abc   abc 
abby_johnny       def   def   def   def 
a_j               ghi   ghi   ghi   ghi 
abby_(john)       abc   abc   abc   abc 
abby_john_doe     def   def   def   def 
aby_John_Doedy    ghi   ghi   ghi   ghi
abby john         ghi   ghi   ghi   ghi
john_abby_doe     def   def   def   def
aby_/_John_Doedy  ghi   ghi   ghi   ghi
doe jane          abc   abc   abc   abc
doe_jane          def   def   def   def""")

import pandas as pd
df = pd.read_fwf(s,header=None,sep='\s+')
lst_original = df[0].tolist() # the first column 

Vectorize(转成数值表示):

import numpy as np 
from gensim.models import Word2Vec

m = Word2Vec(lst_original,size=50,min_count=1,cbow_mean=1)  
def vectorizer(sent,m): 
    vec = [] 
    numw = 0 
    for w in sent: 
        try: 
            if numw == 0: 
                vec = m[w] 
            else: 
                vec = np.add(vec, m[w]) 
            numw += 1 
        except Exception as e: 
            print(e) 
    return np.asarray(vec) / numw 

l = []
for i in lst_original:
    l.append(vectorizer(i,m))

X = np.array(l)

KMeans clustering:

from sklearn.cluster import KMeans

clf = KMeans(n_clusters=2,init='k-means++',n_init=100,random_state=0)
labels = clf.fit_predict(X)

然后我们只得到集群交替的值:

previous_cluster = 0
for index, sentence in enumerate(lst_original):
    if index > 0:
        previous_cluster = labels[index - 1]
    cluster = labels[index]
    if previous_cluster != cluster:
        print(str(labels[index]) + ":" + str(sentence))

结果,如您所见,a_j 的处理方式与 abby_john 组的其他成员不同:

1:a_j
0:abby_(john)
1:doe jane