如何编写函数以使用python中的迭代通过2个数据框获取价值

时间:2019-06-01 11:32:35

标签: python pandas dataframe

我得到了两个数据帧,长度为2173的A和长度为6135的B。 A称为“文件名”,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')

1 个答案:

答案 0 :(得分:0)

我通过以下方式创建测试数据:

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 )。

该函数从计算当前币种之间的令牌集比率开始 文件名和每个 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,但是原因是 源数据非常有限。