反向查找列表字典中的子字符串
Reverse lookup of a sub-string in a dict of lists
我正在努力寻找一种“pythonic”方式来使这个逻辑起作用:
我有一个包含一列字符串(“受益人”)的支付交易数据框:
index
beneficiary
12
REWE SAGT DANKE. ...
13
NaN
14
OBI BAU- U. HEIMWER//BERLIN/DE / OBI SAGT DANKE
15
NETFLIX INTERNATIONAL B.V.
我需要在我的数据框中创建另一列,这将是每一行所属的类别。
index
beneficiary
category
12
REWE SAGT DANKE. ...
Groceries
14
OBI BAU- U. HEIMWER//BERLIN/DE / OBI SAGT DANKE
Groceries
15
NETFLIX INTERNATIONAL B.V.
Entertainment
我正在考虑制作一个如下所示的字典,并以某种方式反向查找类别字典中带有上面列的子字符串值:
categories = {"Groceries": ["EDEKA", "REWE", "OBI"],
"Entertainment": ["NETFLIX"]}
逻辑是:如果子字符串“REWE”在df['beneficiary']中,那么df['category']等于子字符串所在的dict元素的键。
我对其他映射逻辑持开放态度。
您可以使用正则表达式,为此您需要修改字典,将匹配的字符串作为键,将类别作为值:
categories = {"Groceries": ["EDEKA", "REWE", "OBI"],
"Entertainment": ["NETFLIX"]}
cat_sub = {v:k for k,l in categories.items() for v in l}
regex = r'(%s)' % '|'.join(fr'\b{c}\b' for c in cat_sub)
# regex looks like this: (\bEDEKA\b|\bREWE\b|\bOBI\b|\bNETFLIX\b)
df['category'] = df['beneficiary'].str.extract(regex, expand=False).map(cat_sub)
注意。我使用单词边界 (\b
) 来确保匹配完整的单词,如果你不想要这种行为,请使用 regex = r'(%s)' % '|'.join(cat_sub)
输出:
index beneficiary category
0 12 REWE SAGT DANKE. ... Groceries
1 13 NaN NaN
2 14 OBI BAU- U. HEIMWER//BERLIN/DE / OBI SAGT DANKE Groceries
3 15 NETFLIX INTERNATIONAL B.V. Entertainment
注意。如果需要删除 NaN,请使用 dropna
尝试逆向字典,将每个词映射到一个类别,并将其应用于“beneficiary”中的每个词:
word_cat = {w: k for k,v in categories.items() for w in v}
df["category"] = df["beneficiary"].str.split(expand=True).apply(lambda x: x.map(word_cat)).bfill(axis=1).iloc[:,0]
df = df.dropna()
>>> df
index beneficiary category
0 12 REWE SAGT DANKE. Groceries
2 14 OBI BAU-U. HEIMWER//BERLIN/DE /OBI SAGT DANKE Groceries
3 15 NETFLIX INTERNATIONAL B.V. Entertainment
我正在努力寻找一种“pythonic”方式来使这个逻辑起作用:
我有一个包含一列字符串(“受益人”)的支付交易数据框:
index | beneficiary |
---|---|
12 | REWE SAGT DANKE. ... |
13 | NaN |
14 | OBI BAU- U. HEIMWER//BERLIN/DE / OBI SAGT DANKE |
15 | NETFLIX INTERNATIONAL B.V. |
我需要在我的数据框中创建另一列,这将是每一行所属的类别。
index | beneficiary | category |
---|---|---|
12 | REWE SAGT DANKE. ... | Groceries |
14 | OBI BAU- U. HEIMWER//BERLIN/DE / OBI SAGT DANKE | Groceries |
15 | NETFLIX INTERNATIONAL B.V. | Entertainment |
我正在考虑制作一个如下所示的字典,并以某种方式反向查找类别字典中带有上面列的子字符串值:
categories = {"Groceries": ["EDEKA", "REWE", "OBI"],
"Entertainment": ["NETFLIX"]}
逻辑是:如果子字符串“REWE”在df['beneficiary']中,那么df['category']等于子字符串所在的dict元素的键。
我对其他映射逻辑持开放态度。
您可以使用正则表达式,为此您需要修改字典,将匹配的字符串作为键,将类别作为值:
categories = {"Groceries": ["EDEKA", "REWE", "OBI"],
"Entertainment": ["NETFLIX"]}
cat_sub = {v:k for k,l in categories.items() for v in l}
regex = r'(%s)' % '|'.join(fr'\b{c}\b' for c in cat_sub)
# regex looks like this: (\bEDEKA\b|\bREWE\b|\bOBI\b|\bNETFLIX\b)
df['category'] = df['beneficiary'].str.extract(regex, expand=False).map(cat_sub)
注意。我使用单词边界 (\b
) 来确保匹配完整的单词,如果你不想要这种行为,请使用 regex = r'(%s)' % '|'.join(cat_sub)
输出:
index beneficiary category
0 12 REWE SAGT DANKE. ... Groceries
1 13 NaN NaN
2 14 OBI BAU- U. HEIMWER//BERLIN/DE / OBI SAGT DANKE Groceries
3 15 NETFLIX INTERNATIONAL B.V. Entertainment
注意。如果需要删除 NaN,请使用 dropna
尝试逆向字典,将每个词映射到一个类别,并将其应用于“beneficiary”中的每个词:
word_cat = {w: k for k,v in categories.items() for w in v}
df["category"] = df["beneficiary"].str.split(expand=True).apply(lambda x: x.map(word_cat)).bfill(axis=1).iloc[:,0]
df = df.dropna()
>>> df
index beneficiary category
0 12 REWE SAGT DANKE. Groceries
2 14 OBI BAU-U. HEIMWER//BERLIN/DE /OBI SAGT DANKE Groceries
3 15 NETFLIX INTERNATIONAL B.V. Entertainment