Python 在dataframe列中应用模糊匹配,并将结果保存在新列中

Python 在dataframe列中应用模糊匹配,并将结果保存在新列中,python,pandas,fuzzy-search,fuzzywuzzy,Python,Pandas,Fuzzy Search,Fuzzywuzzy,我有两个数据帧,每个数据帧的行数不同。下面是每个数据集中的几行 df1 = Company City State ZIP FREDDIE LEES AMERICAN GOURMET SAUCE St. Louis MO 63101 CITYARCHRIVER 2015 FOUNDATION St. Louis MO 6

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

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

我使用
combined_data=pandas.concat([df1,df2],axis=1)将它们并排连接起来。我的下一个目标是使用
fuzzy wuzzy
模块中的几个不同匹配命令,将
df1['Company']
下的每个字符串与
df2['FDA Company']
下的每个字符串进行比较,并返回最佳匹配的值及其名称。我想把它存储在一个新的列中。例如,如果我在
df1['Company']
df2['FDA Company']中的
LACKY钣金上执行
fuzz.ratio
fuzz.token\u sort\u ratio
它将返回最佳匹配是
分数为
100的劣质钣金
,然后将其保存在
组合数据中的新列下。结果会是这样的

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) 
但由于列的长度不同,因此出现错误


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

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

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'])
指标
应用于
比较
系列

compare.apply(metrics)

下一部分有很多方法:

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

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

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

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

这是一个很好的答案!但是,对于大文件(~lakhs),我得到了内存错误我得到了一个
TypeError:type'float'的对象没有len()
,有什么想法吗?我得到了一个TypeError:type'float'的对象没有len(),那么当你应该有字符串时,你有一个float值。你可以通过某种类型的类型转换
.astype(str)
来掩盖这一点,但这可能是一个更大的问题。我会检查你为什么在你尝试使用的任何列中都有浮点数。为什么还要费心并排加入表呢?您最终想要测试df1中的每个名称到df2中的每个名称,并选择得分最高的名称,对吗?一个包含df2.name.apply(fuzz.ratio(…))的简单ItErrorws循环应该可以做到这一点。@NikhilVJ您能展示一下您的方法吗。我没有找到工作的答案。我收到TypeError:类型为“float”的对象没有包含地址数据的len()。@Chris很抱歉,我现在无法使用命令,已转移到其他项目。总体思路:从df1中获取元素X。在df2中,do
df2.score=df2.name.apply(lambda x:fuzz.ratio(x,x))
。然后,按分数对df2排序,取分数最高的行,这是假定的X匹配,因此将其复制到新列中的df1。迭代到下一个X值并重复。
compare.apply(metrics).unstack(0).idxmax().unstack(0)