Python 如何在近似字符串上合并?

Python 如何在近似字符串上合并?,python,pandas,Python,Pandas,我想将大约国家/地区名称上的2个数据框合并到,但我得到以下错误: TypeError:“非类型”对象不可调用 请参见下面的说明性代码: cl = {'Country' : ["Brazil", "US", "Russia"], 'BL?':['No', 'No','Yes']} clist = pd.DataFrame.from_dict(cl) cd = {'Country' : ["Braizl", "us", "Rusia"]} cdata = pd.DataFrame.from_d

我想将大约国家/地区名称上的2个数据框合并到,但我得到以下错误:

TypeError:“非类型”对象不可调用

请参见下面的说明性代码:

cl =  {'Country' : ["Brazil", "US", "Russia"], 'BL?':['No', 'No','Yes']}
clist = pd.DataFrame.from_dict(cl)

cd = {'Country' : ["Braizl", "us", "Rusia"]}
cdata  = pd.DataFrame.from_dict(cd)

clist = clist.sort_values('Country')
cdata = cdata.sort_values('Country')


cdata = pd.merge_asof(cdata,clist,on='Country')  
预期结果将合并两个dfs,cdata df的“BL”列将包含YES/NO值


提前谢谢你

根据你的例子,我找到了一个解决方案。这不是很像蟒蛇,但很管用!(假设您在
clist
中为每个
cdata
错售国家/地区提供了匹配的国家/地区名称)

我正在使用库来计算levenshtein距离。 您可以使用pip安装它:

pip install editdistance

这应该会让你接近,但它不会100%准确。你可以用<代码>模糊模糊模糊使用Levenshtein距离计算两个字符串之间的差值:

from fuzzywuzzy import process

# create a choice list
choices = clist['Country'].values.tolist()

# apply fuzzywuzzy to each row using lambda expression
cdata['Close Country'] = cdata['Country'].apply(lambda x: process.extractOne(x, choices)[0])

# merge
cdata.merge(clist, left_on='Close Country', right_on='Country')


  Country_x Close Country Country_y  BL?
0    Braizl        Brazil    Brazil   No
1     Rusia        Russia    Russia  Yes
2        us            US        US   No
您甚至可以返回匹配百分比,如果只想保持匹配值大于85%,则只需保持值>n

添加匹配百分比 可以在合并之前执行布尔索引,以删除不匹配项,然后进行合并:

cdata[['Close Country', 'Percent Match']] = cdata['Close Country'].apply(pd.Series)
cdata = cdata[cdata['Percent Match']>85]
也可以在合并后执行此操作:

merge = cdata.merge(clist, left_on='Close Country', right_on='Country')
merge[merge['Percent Match'] > 85]

fuzzyfuzzy
返回匹配百分比,作为
过程的一部分
函数。在第一个示例中,我通过调用元组的第一个元素删除了它:
process.extractOne(x,choices)[0]
inplace=True
使排序值返回
None
,因为您指定了在placetrue中执行排序的方法,我得到一个非类型对象,在删除InPlace后现在不可调用我编辑了代码我认为
merge\u asof
只适用于整数。如果你不想找到一个字符串与另一个字符串最近的距离,你可以使用levenshtein距离,但我不知道Pandas库中有任何实现。我如何将其应用于两个dict?应该有两个。你能发布你的代码吗?太棒了!非常感谢你!如何返回%match?@TPguru您想将其作为新列吗?是的,将从FuzzyFuzzy导入过程中的
替换为从rapidfuzz导入过程中的
。您将看到在相同的结果下执行时间的大幅改进
from fuzzywuzzy import process

# create a choice list
choices = clist['Country'].values.tolist()

# apply fuzzywuzzy to each row using lambda expression
cdata['Close Country'] = cdata['Country'].apply(lambda x: process.extractOne(x, choices))

# add percent match wiht apply
cdata[['Close Country', 'Percent Match']] = cdata['Close Country'].apply(pd.Series)

# merge
cdata.merge(clist, left_on='Close Country', right_on='Country')

  Country_x Close Country  Percent Match Country_y  BL?
0    Braizl        Brazil             83    Brazil   No
1     Rusia        Russia             91    Russia  Yes
2        us            US            100        US   No
cdata[['Close Country', 'Percent Match']] = cdata['Close Country'].apply(pd.Series)
cdata = cdata[cdata['Percent Match']>85]
merge = cdata.merge(clist, left_on='Close Country', right_on='Country')
merge[merge['Percent Match'] > 85]