首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python -模糊字符串匹配- TypeError:预期的类似字符串或字节的对象

Python -模糊字符串匹配- TypeError:预期的类似字符串或字节的对象
EN

Stack Overflow用户
提问于 2020-05-20 16:10:51
回答 1查看 389关注 0票数 0

我正在尝试使用以下代码在Python中模糊合并两个数据帧:

代码语言:javascript
复制
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')

其思想是基于每个数据帧的两列(名称和年份)进行模糊合并。我尝试在一个字段(NamePeriod)中合并这两个字段,然后在该字段上合并,但我得到了以下错误:

代码语言:javascript
复制
TypeError: expected string or bytes-like object

你知道如何执行这种模糊合并吗?下面是这些列在数据帧中的外观:

代码语言:javascript
复制
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]

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

代码语言:javascript
复制
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

EN

回答 1

Stack Overflow用户

发布于 2020-05-20 19:02:15

总结一下问题:

  • 有两个DataFrames,它们都有一个name和
  • 的键您想要合并这两个DataFrames并移除所有重复的元素,重复的元素是具有相同年份和非常相似名称的元素

我正在使用以下两个示例DataFrames:

代码语言:javascript
复制
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]})

我解决这个问题的方法是从连接两个数据帧开始

代码语言:javascript
复制
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和匹配算法,看看哪一个最适合您的需求。

代码语言:javascript
复制
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)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61908184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档