【问题标题】:Reverse lookup of a sub-string in a dict of lists反向查找列表字典中的子字符串
【发布时间】:2021-12-22 11:02:22
【问题描述】:

我正在努力寻找一种“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元素的key。

我对其他映射逻辑持开放态度。

【问题讨论】:

  • 这样的规则有多少,受益人姓名有多长?如果这些数字变大,基于 trie 的算法可能是最渐近有效的。如果这些数字很小,最好只扫描每个关键字的每个受益人。

标签: python pandas list dictionary categories


【解决方案1】:

您可以使用正则表达式,为此您需要修改字典以将匹配的字符串作为键和类别作为值:

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

【讨论】:

    【解决方案2】:

    尝试反转您的字典,将每个单词映射到一个类别,并将其应用于“受益人”中的每个单词:

    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
    

    【讨论】:

      猜你喜欢
      • 2016-04-13
      • 1970-01-01
      • 2010-09-06
      • 2012-05-16
      • 2021-01-21
      • 2023-04-03
      • 2018-09-27
      • 1970-01-01
      相关资源
      最近更新 更多