I have a large dataframe in the following form:
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
The same underlying financial instrument will often be held by multiple asset managers but described in a slightly different manner as shown in the table above (e.g. "Four Seasons 1st Lien TL" vs. "Four Seasons 1L Term Loan").
I am trying to figure out the best way to make certain replacements to the "InvestmentDesc" column in the pandas dataframe (e.g. replace "Term Loan" with "TL", replace "1st Lien" with "1L"), ideally (i) in a way that doesn't have to repeatedly loop through several million rows for each term, and (ii) in a way that can be used on a handful of other columns in the dataframe but using a separate list of terms to replace.
I currently have the following function:
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
Into which I am then trying to pass a list of terms to replace (what I assume is a dictionary?) and the existing dataframe column to be modified:
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
However upon doing so, I end up with "TypeError: expected string or bytes-like object" as shown below:
---------------------------------------------------------------------------
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):
pandas\_libs\lib.pyx in pandas._libs.lib.map_infer()
<ipython-input-10-a37630bdc5a4> in <lambda>(x)
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
<ipython-input-10-a37630bdc5a4> in replace_all(dictReplace, text)
18 rep = dict((re.escape(k), v) for k, v in dictReplace.items())
19 pattern = re.compile("|".join(rep.keys()))
---> 20 text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)
21 return text
22
TypeError: expected string or bytes-like object
After two days of googling-until-frustration I simply cannot figure out what I am doing wrong or how to fix. Any advice or thoughts as to how I should proceed would be greatly appreciated!