猿问

替换数据框列中的多个字符串的函数 - “TypeError:预期的字符串或类似字节的对象”

我有以下形式的大型数据框:


FundManager | AsOfDate | InvestmentDesc | Amount  

ManagerA | 6/1/2020 | Four Seasons 1st lien TL | 25500.86  

ManagerA | 6/1/2020 | Arden Group First Lien TL | 28731.00  

ManagerB | 6/1/2020 | Four Seasons 1L Term Loan | 16853.00  

ManagerB | 6/1/2020 | Arden 1st Lien Term Loan | 50254.30

相同的基础金融工具通常由多个资产管理人持有,但描述方式略有不同,如上表所示(例如“四季 1st 留置权 TL”与“四季 1L 定期贷款”)。


我正在尝试找出对 pandas 数据框中的“InvestmentDesc”列进行某些替换的最佳方法(例如,将“Term Loan”替换为“TL”,将“1st Lien”替换为“1L”),理想情况下(i)以一种不必为每个术语重复遍历数百万行的方式,以及 (ii) 可以在数据框中的少数其他列上使用但使用单独的术语列表进行替换的方式。


我目前有以下功能:


def replace_all(dictReplace, text):

    rep = dict((re.escape(k), v) for k, v in dictReplace.items())

    pattern = re.compile("|".join(rep.keys()))

    text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)

    return text

然后我试图将要替换的术语列表传递到其中(我假设是字典?)和要修改的现有数据框列:


dictRepStrings = {"1st lien": "1l", "first lien": "1l", "2nd lien": "2l", "second lien": "2l", "term loan": "tl"}

df['NewCol'] = df['InvestmentDesc'].apply(lambda x: replace_all(dictRepStrings, df['InvestmentDesc']))

df

然而,在这样做时,我最终得到“TypeError: expected string or bytes-like object”,如下所示:


---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-10-a37630bdc5a4> in <module>

     23 

     24 dictRepStrings = {"1st lien": "1l", "first lien": "1l", "2nd lien": "2l", "second lien": "2l", "term loan": "tl"}

---> 25 df['NewCol'] = df['InvestmentDesc'].apply(lambda x: replace_all(dictRepStrings, df['InvestmentDesc']))

     26 df


~\anaconda3\lib\site-packages\pandas\core\series.py in apply(self, func, convert_dtype, args, **kwds)

   3846             else:

   3847                 values = self.astype(object).values

-> 3848                 mapped = lib.map_infer(values, f, convert=convert_dtype)

   3849 

   3850         if len(mapped) and isinstance(mapped[0], Series):

经过两天的谷歌搜索直到沮丧,我根本无法弄清楚我做错了什么或如何解决。任何关于我应该如何进行的建议或想法将不胜感激!


喵喵时光机
浏览 131回答 3
3回答

白衣非少年

如果您有大型数据集,我会尝试使用numpy.selectand pandas.str.contains:import numpy as npimport pandas as pddf["NewCol"] = np.select(    condlist=[        df["InvestmentDesc"].str.contains("1st lien|first lien", case=False, na=False),        df["InvestmentDesc"].str.contains("2nd lien|second lien", case=False, na=False),        df["InvestmentDesc"].str.contains("term loan", case=False, na=False),    ],    choicelist=[        "1l", "2l", "tl"    ],    default=df["InvestmentDesc"])

郎朗坤

您的应用函数存在语法问题。您不是将单个文本和字典作为参数传递,而是InvestmentDesc在应用程序中传递整个系列 ( ) 列。因此,该函数在使用 的调用期间失败lambda。必需的:replace_all(dictReplace, text)鉴于:replace_all(dictRepStrings, df['InvestmentDesc'])您可以自己解决这个问题,但为了可读性,我建议您进行一些小的更改。尝试将其与args参数一起使用。def replace_all(text, dictReplace): #Made dictReplace as second parameter&nbsp; &nbsp; rep = dict((re.escape(k), v) for k, v in dictReplace.items())&nbsp; &nbsp; pattern = re.compile("|".join(rep.keys()))&nbsp; &nbsp; text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)&nbsp;&nbsp; &nbsp; return textdictRepStrings = {"1st lien": "1l", "first lien": "1l", "2nd lien": "2l", "second lien": "2l", "term loan": "tl"}df['NewCol'] = df['InvestmentDesc'].apply(replace_all, args=[dictRepStrings]) #modified apply function with argsdf请注意,我通过删除更改了应用函数的结构lambda,添加了args参数并将其作为dict函数中的第二个参数,因此apply将每一行作为dict第一个参数传递,第二个参数定义在args这对我有用,如果您仍然遇到问题,请告诉我。

杨魅力

你也可以像这样做一些相对简单的事情:def replacer(desc, replacers):&nbsp; &nbsp; for key in replacers.keys():&nbsp; &nbsp; &nbsp; &nbsp; if key in desc.lower():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; desc = desc.lower().replace(key, replacers[key]).title()&nbsp; &nbsp; return descreplacers = {'1st lien': '1l', 'first lien': '1l', '2nd lien': '2l', 'second lien': '2l', 'term loan': 'tl'}df['InvestmentDesc'].apply(replacer, replacers=replacers)输出:0&nbsp; &nbsp; Four Seasons 1L Tl1&nbsp; &nbsp; &nbsp;Arden Group 1L Tl2&nbsp; &nbsp; Four Seasons 1L Tl3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Arden 1L Tl不确定大写是否重要,或者你可以稍微调整一下以获得你想要的大写。但我认为这是一个非常简单的解决方案,并且还将考虑每个字符串中的多个匹配项也许可以针对不区分大小写的正则表达式搜索/替换修改它,但原理相同
随时随地看视频慕课网APP

相关分类

Python
我要回答