不同数据框的模糊匹配列

时间:2018-09-10 11:11:37

标签: python pandas fuzzy-logic fuzzy-comparison fuzzywuzzy

背景

我有2个没有通用密钥的数据框,可以将它们合并到其中。两个df都有一个包含“实体名称”的列。一个df包含8000多个实体,另一个df包含近2000个实体。

样本数据

vendor_df=
     Name of Vendor                             City         State  ZIP
     FREDDIE LEES AMERICAN GOURMET SAUCE       St. Louis    MO     63101
     CITYARCHRIVER 2015 FOUNDATION             St. Louis    MO     63102
     GLAXOSMITHKLINE CONSUMER HEALTHCARE       St. Louis    MO     63102
     LACKEY SHEET METAL                        St. Louis    MO     63102

regulator_df = 
     Name of Entity                    Committies
     LACKEY SHEET METAL                 Private
     PRIMUS STERILIZER COMPANY LLC      Private  
     HELGET GAS PRODUCTS INC            Autonomous
     ORTHOQUEST LLC                     Governmant  

问题说明:

我必须模糊匹配这两列(Name of vendorName of Entity)的实体并获得一个分数。因此,需要知道数据帧1(vendor_df)的第一个值是否与数据帧2( regulator_df )的2000个实体中的任何一个匹配。

我检查过的StackOverflow链接

  

fuzzy match between 2 columns (Python)

     

create new column in dataframe using fuzzywuzzy

     

Apply fuzzy matching across a dataframe column and save results in a new column

代码

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process

vendor_df = pd.read_excel('C:\\Users\\40101584\\Desktop\\AUS CUB AML\\Vendors_Sheet.xlsx', sheet_name=0)

regulator_df = pd.read_excel('C:\\Users\\40101584\\Desktop\\AUS CUB AML\\Regulated_Vendors_Sheet.xlsx', sheet_name=0)

compare = pd.MultiIndex.from_product([vendor_df['Name of vendor'],
                                      regulator_df['Name of Entity']]).to_series()


def metrics(tup):
    return pd.Series([fuzz.ratio(*tup),
                      fuzz.token_sort_ratio(*tup)],
                     ['ratio', 'token'])

#compare.apply(metrics) -- Either this works or the below line

result = compare.apply(metrics).unstack().idxmax().unstack(0)

上述代码有问题

如果两个数据框都很小,则代码可以工作,但是当我给出完整的数据集时,它会花费很多时间。上面的代码摘自第3个链接。

是否可以通过相同的方法快速运行或可以使用大型数据集?

更新1

如果我们通过或硬编码得分为80(仅使用Fuzzyscore> 80过滤系列/数据框)的得分,可以使上述代码更快?

2 个答案:

答案 0 :(得分:1)

以下解决方案比我发布的解决方案要快,但是如果有人有更快的解决方法,请告知:

matched_vendors = []

for row in vendor_df.index:
    vendor_name = vendor_df.get_value(row,"Name of vendor")
    for columns in regulator_df.index:
        regulated_vendor_name=regulator_df.get_value(columns,"Name of Entity")
        matched_token=fuzz.partial_ratio(vendor_name,regulated_vendor_name)
        if matched_token> 80:
            matched_vendors.append([vendor_name,regulated_vendor_name,matched_token])

答案 1 :(得分:0)

就我而言,我也只需要查找80以上的值。我根据用例修改了您的代码。希望有帮助。

compare = compare.apply(metrics)
compare_80=compare[(compare['ratio'] >80) & (compare['token'] >80)]