【问题标题】:Apply fuzzy matching across a dataframe column and save results in a new column在数据框列中应用模糊匹配并将结果保存在新列中
【发布时间】:2016-11-29 08:40:01
【问题描述】:

我有两个数据框,每个数据框都有不同的行数。下面是每个数据集的几行

df1 =
     Company                                   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

和

df2 = 
     FDA Company                    FDA City    FDA State   FDA ZIP
     LACKEY SHEET METAL             St. Louis   MO          63102
     PRIMUS STERILIZER COMPANY LLC  Great Bend  KS          67530
     HELGET GAS PRODUCTS INC        Omaha       NE          68127
     ORTHOQUEST LLC                 La Vista    NE          68128

我使用combined_data = pandas.concat([df1, df2], axis = 1) 并排加入了他们。我的下一个目标是使用来自fuzzy wuzzy 模块的几个不同的匹配命令将df1['Company'] 下的每个字符串与df2['FDA Company'] 下的每个字符串进行比较,并返回最佳匹配的值及其名称。我想将其存储在新列中。例如,如果我在df1['Company'] 到df2['FDA Company'] 中对LACKY SHEET METAL 执行fuzz.ratio 和fuzz.token_sort_ratio,它将返回最佳匹配是LACKY SHEET METAL,得分为100,然后将其保存在combined data 中的新列。结果看起来像

combined_data =
     Company                                   City         State  ZIP      FDA Company                     FDA City    FDA State   FDA ZIP     fuzzy.token_sort_ratio    match    fuzzy.ratio         match
     FREDDIE LEES AMERICAN GOURMET SAUCE       St. Louis    MO     63101    LACKEY SHEET METAL              St. Louis   MO          63102       LACKEY SHEET METAL        100      LACKEY SHEET METAL  100
     CITYARCHRIVER 2015 FOUNDATION             St. Louis    MO     63102    PRIMUS STERILIZER COMPANY LLC   Great Bend  KS          67530
     GLAXOSMITHKLINE CONSUMER HEALTHCARE       St. Louis    MO     63102    HELGET GAS PRODUCTS INC         Omaha       NE          68127
     LACKEY SHEET METAL                        St. Louis    MO     63102    ORTHOQUEST LLC                  La Vista    NE          68128

我试过了

combined_data['name_ratio'] = combined_data.apply(lambda x: fuzz.ratio(x['Company'], x['FDA Company']), axis = 1) 

但由于列的长度不同而出错。

我被难住了。我怎样才能做到这一点?

【问题讨论】:

  • 为什么要并排加入表格?您最终希望将 df1 中的每个名称与 df2 中的每个名称进行测试,然后选择得分最高的名称,对吗?一个带有 df2.name.apply(fuzz.ratio(...)) 的简单 iterrows 循环应该可以做到。
  • @NikhilVJ 你能展示你的方法吗?我没有得到可以解决问题的方法。我收到 TypeError:'float' 类型的对象没有带有地址数据的 len()。
  • @Chris 抱歉,我现在与命令格格不入,已转移到其他项目。总体思路:从 df1 中获取元素 X。在 df2 中,执行 df2.score = df2.name.apply(lambda x: fuzz.ratio(x,X)) 。然后,按分数对 df2 进行排序,取出分数最高的行,这是 X 的假定匹配项,因此将其复制到 df1 的新列中。迭代到下一个 X 值并重复。

标签: python pandas fuzzy-search fuzzywuzzy


【解决方案1】:

我不知道你在做什么。我就是这样做的。

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

创建一系列元组进行比较:

compare = pd.MultiIndex.from_product([df1['Company'],
                                      df2['FDA Company']]).to_series()

创建一个特殊的函数来计算模糊度量并返回一个序列。

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

将metrics 应用于compare 系列

compare.apply(metrics)

下一部分有很多方法可以做到这一点:

获取与df1 的每一行最接近的匹配项

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

获取与df2每一行最接近的匹配项

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

【讨论】:

  • 这是一个很好的答案!但是,对于大文件(〜十万),我得到内存错误
  • 我收到了TypeError: object of type 'float' has no len(),有什么想法吗?
  • 我得到一个 TypeError:'float' 类型的对象没有 len()
  • 那么当你应该有字符串时你有一个浮点值。您可以通过某种类型的类型转换.astype(str) 来掩盖这一点,但这可能是一个更大的问题。我会检查为什么您在尝试使用的任何列中都有浮动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 2019-02-14
  • 2021-12-16
相关资源
最近更新 更多