【问题标题】:Creating flag using fuzzywuzzy matching between two datasets in python在python中的两个数据集之间使用fuzzywuzzy匹配创建标志
【发布时间】:2018-09-27 02:13:07
【问题描述】:

我有两个数据集 df1 和 df2 ,都有以下列:

|city   |state  |address_id |address             |postal_code
|A      |X      |10         |flat 123,abc lane   |400000

我想根据 df2 中是否存在类似地址,为 df1 中的每个 address_id 创建一个二进制标志。我的原始数据集非常大(df1= 5k 行,df2= 200K 行)。我在小数据样本上尝试了以下代码集:

for i in df1.index:
      v=[]
      for j in df2.index:
            vi = df1.get_value(i, 'address')
            vj = df2.get_value(j, 'address')
            v.append(max(fuzz.ratio(vi, vj),
               fuzz.partial_ratio(vi, vj),
               fuzz.token_sort_ratio(vi, vj),
               fuzz.token_set_ratio(vi, vj)))
      vmax=max(v)
      if vmax>=80:
           df1.loc[i,'flag']='Y'
      else:
           df1.loc[i,'flag']='N' 

但这不适用于更大的数据集。有没有办法优化这个? postal_code 可以用作模糊匹配时的条件,以减少迭代次数。另外,也许我可以在达到 v=80 时立即停止迭代。

for i in df1.index:
    v=1
    while v<=80:
        for j in df2.index:
            vi = df1.get_value(i, 'address')
            vj = df2.get_value(j, 'address')
            v= max(fuzz.ratio(vi, vj),
               fuzz.partial_ratio(vi, vj),
               fuzz.token_sort_ratio(vi, vj),
               fuzz.token_set_ratio(vi, vj))
        if v>=80:
           df1.loc[i,'flag']='Y'
        else:
           df1.loc[i,'flag']='N'

刚开始使用 python,所以有点卡在这里。请帮忙!

【问题讨论】:

    标签: python pandas fuzzywuzzy


    【解决方案1】:

    我在 2 个 DF 上尝试了一些模糊的比较,就我的研究而言,没有快速的方法可以做到这一点。您使用 4 个fuzz 方法的事实也会减慢您的脚本速度。一种方法是使用“process.extractOne()”并创建一个这样的函数:

    from fuzzywuzzy import process
    def fw_process(row_df1):
        # Select the addresses from df2 with same postal_code
        df2_select_add = df2['address'][df2['postal_code'] == row_df1['postal_code']]
        ad_1 = row_df1['address']
        # Find the best match for ad_1 in df2_select_add and get the ratio with [1] 
        # for the name of df2_select_add , use [0]
        if process.extractOne(ad_1, df2_select_add)[1] >= 80:
            return 'Y'
        else:
            return 'N'
    

    然后要在df1 中创建您的列标志,您可以:

    df1['flag'] = df1.apply(fw_process , axis=1)
    

    注意:名称df2 不作为函数的参数调用,这不是更简洁的方法,但如果它之前在您的代码中使用此名称定义,则它可以工作。

    如果你想保留这4个fuzz方法,那么你可以按照同样的思路创建函数:

    from fuzzywuzzy import fuzz
    def fw_fuzz ( row_df1):
        # Select the addresses from df2 with same postal_code
        df2_select_add = df2['address'][df2['postal_code'] == row_df1['postal_code']]
        ad_1 = row_df1['address']
        # Get the max of the max of the 4 fuzz comparison between ad_1 and df2_select_add
        if max (df2_select_add.apply(lambda x: max(fuzz.ratio(ad_1, x), fuzz.partial_ratio(ad_1, x),
                                                    fuzz.token_sort_ratio(ad_1, x),fuzz.token_set_ratio(ad_1, x)))) >= 80:
            return 'Y'
        else:
            return 'N'
    

    然后:

    df1['flag'] = df1.apply(fw_fuzz, axis=1)
    

    【讨论】:

    • 在运行第一个代码时,我收到以下错误:文件 "", line 7, in fw_process if process.extractOne(ad_1, df2_select_add)[1 ] >= 80: TypeError: ("'NoneType' object is not subscriptable", '发生在索引 0') 。在运行第二个代码时,我收到此错误: File "", line 6, in fw_fuzz if max (df2_select_add.apply(lambda x: max(fuzz.ratio(ad_1, x), fuzz.partial_ratio(ad_1, x), ValueError: ('max() arg is an empty sequence', 'occured at index 0')。请帮忙。
    • 您的问题可能是df1 中有一些postal_code 而不是df2,那么您有一个空的df2_select_add。一种选择是检查df2_select_add 是否为空。在'df2_select_add = ...'行之后,您可以添加if df2_select_add.empty: return 'N'
    猜你喜欢
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    相关资源
    最近更新 更多