Python - 模糊字符串匹配 - TypeError: expected string or bytes-like object.

问题描述 投票:0回答:1

我正试图使用下面的代码在Python中对两个数据框进行模糊合并。

import pandas as pd
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
    prospectus_data_file = 'file1.xlsx'
    filings_data_file = 'file2.xlsx'
    prospectus = pd.read_excel(prospectus_data_file)
    filings = pd.read_excel(filings_data_file)
    #all_data_st = pd.merge(prospectus, filings, on='NamePeriod')   
    filings['key']=filings.NamePeriod.apply(lambda x : [process.extract(x, prospectus.NamePeriod, limit=1)][0][0][0])
    all_data_st = filings.merge(prospectus,left_on='key',right_on='NamePeriod')
    all_data_st.to_excel('merged_file_fuzzy.xlsx')

我们的想法是基于每个数据框的两列--Name和Year--进行模糊合并。我试图将这两列合并到一个字段(NamePeriod)中,然后再进行合并,但我得到了以下错误。

TypeError: expected string or bytes-like object

有什么办法可以执行这个模糊的合并吗?下面是这些列在数据框中的样子。

print(filings[['Name', 'Period','NamePeriod']])
print(prospectus[['prospectus_issuer_name', 'fyear','NamePeriod']])



print(filings[['Name', 'Period','NamePeriod']])
print(prospectus[['prospectus_issuer_name', 'fyear','NamePeriod']])
                                               Name  ...                  NamePeriod
0                                               NaN  ...                         NaN
1                             NAM TAI PROPERTY INC.  ...  NAM TAI PROPERTY INC. 2019
2                             NAM TAI PROPERTY INC.  ...  NAM TAI PROPERTY INC. 2018
3                             NAM TAI PROPERTY INC.  ...  NAM TAI PROPERTY INC. 2017
4                             NAM TAI PROPERTY INC.  ...  NAM TAI PROPERTY INC. 2016
                                            ...  ...                         ...
15922                   Huitao Technology Co., Ltd.  ...                         NaN
15923                       Leaping Group Co., Ltd.  ...                         NaN
15924                                    PUYI, INC.  ...                         NaN
15925  Puhui Wealth Investment Management Co., Ltd.  ...                         NaN
15926                           Tidal Royalty Corp.  ...                         NaN

[15927 rows x 3 columns]
           prospectus_issuer_name  fyear                        NamePeriod
0                  ALCAN ALUM LTD   1990               ALCAN ALUM LTD 1990
1                  ALCAN ALUM LTD   1991               ALCAN ALUM LTD 1991
2                  ALCAN ALUM LTD   1992               ALCAN ALUM LTD 1992
3               AMOCO CDA PETE CO   1992            AMOCO CDA PETE CO 1992
4               AMOCO CDA PETE CO   1992            AMOCO CDA PETE CO 1992
                          ...    ...                               ...
1798               KOREA GAS CORP   2016               KOREA GAS CORP 2016
1799               KOREA GAS CORP   2016               KOREA GAS CORP 2016
1800          PETROLEOS MEXICANOS   2016          PETROLEOS MEXICANOS 2016
1801          PETROLEOS MEXICANOS   2016          PETROLEOS MEXICANOS 2016
1802  BOC AVIATION PTE LTD GLOBAL   2016  BOC AVIATION PTE LTD GLOBAL 2016

[1803 rows x 3 columns]

以下是我尝试运行的完整代码:

import pandas as pd
from rapidfuzz import process, utils
prospectus_data_file = 'file1.xlsx'
filings_data_file = 'file2.xlsx'


prospectus = pd.read_excel(prospectus_data_file)
filings = pd.read_excel(filings_data_file)



filings.rename(columns={'Name': 'name', 'Period': 'year'}, inplace=True)
prospectus.rename(columns={'prospectus_issuer_name': 'name', 'fyear': 'year'}, inplace=True)
df3 = pd.concat([filings, prospectus], ignore_index=True)





from rapidfuzz import fuzz, utils

df3.dropna(subset = ["name"], inplace=True)
names = [utils.default_process(x) for x in df3['name']]
for i1, row1 in df3.iterrows():
    for i2 in df3.loc[(df3['year'] == row1['year']) & (df3.index > i1)].index:
        if fuzz.WRatio(names[i1], names[i2], processor=None, score_cutoff=90):
            df3.drop(i2, inplace=True)

df3.reset_index(inplace=True)

给我一个错误 IndexError: list index out of range

python fuzzy-search
1个回答
1
投票

总结一下这个问题。

  • 有两个DataFrames,它们都有一个名字和年份的键。

  • 您想合并两个DataFrames,并删除所有重复的元素,重复的元素是指具有相同年份和非常相似名称的元素。

我正在处理以下两个DataFrames示例。

import pandas as pd

df1 = pd.DataFrame({
    'Name': ['NAM PROPERTY INC.', 'NAM PROPERTY INC.', 'ALCAN ALUM LTD'],
    'Period': [2019, 2019, 2018]})

df2 = pd.DataFrame({
    'prospectus_issuer_name': ['NAM TAI PROPERTY INC.', 'ALCAN ALUM LTD', 'AMOCO CDA PETE CO'],
    'fyear': [2019, 2019, 1992]})

我对这个问题的处理方法是先把两个数据帧合并起来。

df1.rename(columns={'Name': 'name', 'Period': 'year'}, inplace=True)
df2.rename(columns={'prospectus_issuer_name': 'name', 'fyear': 'year'}, inplace=True)
df3 = pd.concat([df1, df2], ignore_index=True)

之后,可以在这个新的DataFrame上迭代,删除所有重复的行。我使用的是 RapidFuzz 这里,因为它比FuzzyWuzzy快(我是作者)。下面的代码是提前创建一个预处理后的名称列表,因为这些条目可能会被多次使用,而预处理会占用大量的运行时间。之后,它对这些行进行迭代,并总是与所有具有较高指数的行进行比较(具有较低指数的行已经被比较过了,因为ratio(a,b) == ratio(b,a)),并且具有正确的年份。在正确的年份上进行过滤,可以减少运行慢速字符串匹配算法的次数。对于所有年份相近且名称非常相似的行,第一行会被保留,其他行会被删除。你可能需要玩玩 score_cutoff 和匹配算法,看看哪个最适合你的需求。

from rapidfuzz import fuzz, utils

names = [utils.default_process(x) for x in df3['name']]
for i1, row1 in df3.iterrows():
    for i2 in df3.loc[(df3['year'] == row1['year']) & (df3.index > i1)].index:
        if fuzz.WRatio(names[i1], names[i2], processor=None, score_cutoff=90):
            df3.drop(i2, inplace=True)

df3.reset_index(inplace=True)
© www.soinside.com 2019 - 2024. All rights reserved.