【问题标题】:Group by fuzzy string matches with fuzzywuzzy and groupbyGroup by 模糊字符串匹配与fuzzywuzzy 和groupby
【发布时间】:2020-05-26 15:29:03
【问题描述】:

我有一个随机单词和名称的数据集,我正在尝试对所有相似的单词和名称进行分组。所以给出下面的数据框:

     Name           ID            Value
0    James           1             10
1    James 2         2             142
2    Bike            3             1
3    Bicycle         4             1197
4    James Marsh     5             12
5    Ants            6             54
6    Job             7             6
7    Michael         8             80007  
8    Arm             9             47 
9    Mike K          10            9
10   Michael k       11            1

我的伪代码是这样的:

import pandas as pd
from fuzzywuzzy import fuzz

minratio = 95
for idx1, name1 in df['Name'].iteritems():
   for idx2, name2 in df['Name'].iteritems():
      ratio = fuzz.WRatio(name1, name2)
      if ratio > minratio:
          grouped = df.groupby(['Name', 'ID'])['Value']\
                        .agg(Total_Value='sum', Group_Size='count')

这会给我想要的输出:

print(grouped)
     Name           ID            Total_Value          Group_Size
0    James           1             164                     3 # All James' grouped
2    Bike            3             1198                    2 # Bike's and Bicycles grouped
5    Ants            6             54                      1 
6    Job             7             6                       1
7    Michael         8             80017                   3 # Mike's and Michael's grouped
8    Arm             9             47                      1

显然这不起作用,老实说,我不确定这是否可能,但这就是我想要完成的。任何能让我走上正轨的建议都会很有用。

【问题讨论】:

    标签: python pandas fuzzywuzzy


    【解决方案1】:

    使用affinity propagation clustering(不完美,但可能是一个起点):

    import pandas as pd
    import numpy as np
    import io
    from fuzzywuzzy import fuzz
    from scipy import spatial
    import sklearn.cluster
    
    s="""Name           ID            Value
    0    James           1             10
    1    James 2         2             142
    2    Bike            3             1
    3    Bicycle         4             1197
    4    James Marsh     5             12
    5    Ants            6             54
    6    Job             7             6
    7    Michael         8             80007  
    8    Arm             9             47 
    9    Mike K          10            9
    10   Michael k       11            1"""
    df = pd.read_csv(io.StringIO(s),sep='\s\s+',engine='python')
    
    names = df.Name.values
    sim = spatial.distance.pdist(names.reshape((-1,1)), lambda x,y: fuzz.WRatio(x,y))
    affprop = sklearn.cluster.AffinityPropagation(affinity="precomputed", random_state=None)
    affprop.fit(spatial.distance.squareform(sim))
    
    res = df.groupby(affprop.labels_).agg(
            Names=('Name',','.join),
            First_ID=('ID','first'),
            Total_Value=('Value','sum'),
            Group_Size=('Value','count')
            )
    

    结果

                                    Names  First_ID  Total_Value  Group_Size
    0  James,James 2,James Marsh,Ants,Arm         1          265           5
    1                        Bike,Bicycle         3         1198           2
    2                                 Job         7            6           1
    3            Michael,Mike K,Michael k         8        80017           3
    

    【讨论】:

    • 为什么这会将AntsArmJames 放在同一类别中?
    • 这似乎没有考虑WRatio
    • 正如我所说,它并不完美。也许可以通过调整一些参数或应用不同的距离度量来改进它(例如,蚂蚁和詹姆斯相距更远)。为什么你认为它不考虑WRatio?事实上,它是聚类的基础。可以打印spatial.distance.squareform(sim)查看距离矩阵。
    • 例如,使用 Damerau-Levenshtein 距离 (pypi.org/project/pyxDamerauLevenshtein),我们得到以下组:'James,James 2,James Marsh', 'Bike,Bicycle,Mike K', 'Ants,Job,Arm', 'Michael,Michael k'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2014-11-02
    • 2015-11-10
    • 2018-05-31
    • 2021-04-19
    • 1970-01-01
    相关资源
    最近更新 更多