python - 如何使用python中的迭代编写函数以通过2个数据帧获取值
问题描述
我有两个数据帧,长度为 2173 的 A 和长度为 6135 的 B。A 称为“file_name”,B 称为“crsp_name”
A.head()
file_name
0 3M CO
1 ABBOTT LABORATORIES
2 ABC INC
3 ALTRIA GROUP INC
4 AMERICAN ELECTRIC POWER CO
B.head()
0 A & E PLASTIK PAK INC
1 A & M FOOD SERVICES INC
2 A A I CORP
3 A A IMPORTING INC
4 A A R CORP
Name: comnam, dtype: object
我试图计算 A 中每个元素与 B 的 fuzz.token_set_ratio 并将它们组合为一个数据帧。例如,计算“3M CO”与 B 中每个元素的比率,并将“3M”和最大比率组合作为数据框中的一行。这样,我期望得到一个shape(2173,2)的数据框
这是我的函数,我尝试使用 'apply' 和我的 'fuzzratio' 函数来计算所需的比率。但是有一个错误,希望有人能给我一个正确的解决方案。
def fuzzratio(x):
global crsp_name
ratio_list = list()
name_list = list()
for i in crsp_name:
ratio = fuzz.token_set_ratio(x,i)
if ratio > 80:
name_list.append(x)
ratio_list.append(ratio)
name_list = pd.DataFrame(name_list)
result = pd.merge(name_list,ratio_list).rename(columns = {'comnam','ratio'})
return result
file_name.apply(fuzzratio)
错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/frame.py", line 6004, in apply
return op.get_result()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/apply.py", line 318, in get_result
return super(FrameRowApply, self).get_result()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/apply.py", line 142, in get_result
return self.apply_standard()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/apply.py", line 248, in apply_standard
self.apply_series_generator()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/apply.py", line 277, in apply_series_generator
results[i] = self.f(v)
File "<stdin>", line 11, in fuzzratio
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/reshape/merge.py", line 60, in merge
validate=validate)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/reshape/merge.py", line 526, in __init__
'type {right}'.format(right=type(right)))
ValueError: ("can not merge DataFrame with instance of type <class 'list'>", 'occurred at index file_name')
解决方案
我通过以下方式创建了测试数据:
dat_A="""file_name
3M CO
ABBOTT LABORATORIES
ABC INC
ALTRIA GROUP INC
AMERICAN ELECTRIC POWER CO"""
dat_B="""crsp_name
A & E PLASTIK PAK INC
A & M FOOD SERVICES INC
A A I CORP
A A IMPORTING INC
A A R CORP
ABBOTT
ABBOTT LABS
ALTRIA
ALTRIA GROUP"""
df_A = pd.read_csv(pd.compat.StringIO(dat_A))
df_B = pd.read_csv(pd.compat.StringIO(dat_B))
因为从df_B只使用了crsp_name列,出于效率原因,我将其提取到crsp变量中:
crsp = df_B.crsp_name
为了便于使用比率阈值进行操作,我将其保存为另一个变量:
ratio_threshold = 50
出于测试目的,我采用了较低的值以获得任何“非空”结果,但对于您的数据,将其设置回80(您定义的值)。
然后我们定义即将应用的函数:
def fn(t1):
ratios = crsp.apply(lambda t2: fuzz.token_set_ratio(t1, t2))
iMax = ratios.idxmax()
rMax = ratios[iMax]
return crsp.loc[iMax] if rMax > ratio_threshold else f'{iMax}_{rMax}'
此函数将应用于df_A.file_name中的每个字符串,因此t1是当前值 ( file_name )。
该函数从计算当前 file_name和每个crsp_name之间的令牌集比率开始(保存在ratios中)。
然后iMax被计算为最大比率和rMax的索引- 最大比率本身。
如果最大比率高于我们的阈值,该函数将返回相应的crsp_name。
否则,该函数将返回“诊断消息” - x_y(2 个数字),其中x是找到最大比率的索引, y - 比率本身。在程序的最终版本中,将其更改为np.nan或空字符串。
唯一要做的就是应用此函数并将结果作为新列添加到df_A:
df_A['crsp_name'] = df_A.file_name.apply(fn)
对于上述测试数据(和阈值 == 50),我得到:
file_name crsp_name
0 3M CO 2_46
1 ABBOTT LABORATORIES ABBOTT
2 ABC INC A & E PLASTIK PAK INC
3 ALTRIA GROUP INC ALTRIA
4 AMERICAN ELECTRIC POWER CO 1_43
如您所见,仍然有 2 种情况,crsp_name中没有位置给出的比率超过 50,但原因是源数据非常有限。
第二种解决方案
当任务是根据候选列表查找匹配项时,更好(更快)的解决方案是使用process.extractOne。
由于它需要一个列表作为第二个参数,我将值 从crsp提取到另一个变量中:
crspVals = crsp.values
要匹配的函数(仅返回最佳匹配)是:
def fn3(t1):
res = process.extractOne(t1, crspVals, scorer=fuzz.token_set_ratio,
score_cutoff=ratio_threshold)
return res[0] if res else ''
process.extractOne
返回一个元组(最佳匹配,比率),但是如果没有找到高于阈值的匹配,则结果为None,所以我决定放弃低于阈值的最佳比率,只返回最佳匹配或空字符串。
要应用此功能,请运行:
df_A['crsp_name'] = df_A.file_name.apply(fn3)
与第一个解决方案(修改为仅返回crsp_name)相比,它的运行速度快了近 2 倍。
推荐阅读
- javascript - 如何使用一个滑块角度同步搜索多个视频
- javascript - jquery简单隐藏显示基于复选框选中
- github - 无法 fork 个人 github 存储库
- c++ - 如何让所有正在运行的线程 C++ 休眠?
- ruby-on-rails - ROR 中 nil:NilClass 的未定义方法“+”
- list - 将 List[String] 转换为 Map[String,String]
- google-cloud-platform - 在 Vertex AI 中将多个模型部署到同一端点
- lambda - 当使用阿波罗服务器 lambda 我得到 {"statusCode":400,"error":"Bad Request","message":"Invalid cookie value"}
- user-controls - 修改现有 FMX 控件的正确方法是什么?
- python - 如何为 DRF 视图集中的每个函数返回自定义消息?