【问题标题】:Matching a word in Pandas column and when creating a new column based on the match匹配 Pandas 列中的单词以及基于匹配创建新列时
【发布时间】:2019-11-29 19:44:37
【问题描述】:

我有一个带有多个列的 pandas 数据框和一个带有键和值作为列表的字典。在 df 一列表示描述,我需要查看此描述并检查它是否与字典列表中的值之一匹配。

这是字典的摘录:

clothing_types = {'T-Shirt': ['t-shirt', 'shirt', 'tee'],
          'Tank Top': ['tank top', 'mesh', 'top', 'tank'],
          'Socks': ['socks'],
          'Hat': ['cap'],
          'Trainers': ['trainers', 'snickers', 'shoes', 'furylite 
          contemporary'}

这是专栏:

0       UNDER ARMOUR LADIES FLY-BY STRETCH MESH TANK TOP
1            UNDER ARMOUR LADIES SPEEDFORM NO SHOW SOCKS
2            UNDER ARMOUR LADIES SPEEDFORM NO SHOW SOCKS
3                     UNDER ARMOUR LADIES PLAY UP SHORTS
4             REEBOK LADIES CLASSIC LEATHER MID TRAINERS
5      UNDER ARMOUR MENS Spring Performance Oxford SHIRT
6       UNDER ARMOUR LADIES HEATGEAR ALPHA SHORTY SHORTS
7                                 ADIDAS LADIES PRO TANK
8                REEBOK LADIES ONE SERIES V NECK T-SHIRT
9                              REEBOK LADIES DF LONG BRA
10                     NIKE LADIES BASELINE TENNIS SKIRT
11              UNDER ARMOUR MENS ESCAPE 7" SOLID SHORTS
12      UNDER ARMOUR LADIES FLY-BY STRETCH MESH TANK TOP

我可以通过正常的for循环进行比较:

for item in self.original_file['Product Description'].tolist():
    found = False
    for item_type, type_descriptions in clothing_types.items():
        for description in type_descriptions:
            if description.upper() in item.upper():
                # print(item_type, item)
                found = True
                break

    if not found:
        print('NOT FOUND', item)

并尝试使用 np.where 来做到这一点:

for item_type, type_descriptions in clothing_types.items():
    for description in type_descriptions:
        self.original_file['Category'] = np.where(description.upper() in self.original_file['Product Description'], item_type, 'None')

但它会用最后一个值比较替换值,这使得列值始终为无

预期如果“衬衫”在描述“T-Shirt”(这是字典的一个键)中将被填充到新列 - 类别中

【问题讨论】:

  • 如果匹配到了怎么办?什么是预期的输出?真/假一列?
  • 我需要填充字典的键,所以如果有衬衫匹配 -> T-Shirt 将被填充

标签: pandas python-2.7 csv numpy python-2.6


【解决方案1】:

这可行,但不确定这是否是最佳解决方案

for i in self.original_file.index:
    for item_type, type_descriptions in clothing_types.items():
        for description in type_descriptions:
            if description.upper() in self.original_file.iloc[i]['Product Description'].upper():
                self.original_file.at[i, 'Category'] = item_type

【讨论】:

    【解决方案2】:

    首先,你应该像这样在你的clothing_types dict中的键和值之间切换

    lothing_types2 = dict(list(itertools.chain(*[[(y_, x) for y_ in y] for x, y in clothing_types.items()])))
    

    (reference)

    然后,创建一个函数来搜索每行,如果您创建的新字典中有任何单词:

    def to_category(x):
        for w in x.lower().split(" "):
            if w in clothing_types2:
                return clothing_types2[w]
        return None
    

    最后,在列上应用方法并将结果保存到一个新的:

    df["Category"] = df["clothing"].apply(to_category)
    

    【讨论】:

      【解决方案3】:

      如果我们找到任何匹配项,我们可以通过str.contains 进行检查。如果我们得到一个命中,我们填写字典的key,否则什么都没有。最后,我们将所有空格和匹配项删除为一列:

      matches = [np.where(df['Product Description'].str.contains('|'.join(v), case=False), 
                          k, 
                          '') for k, v in clothing_types.items()]
      
      matches_df = pd.DataFrame(matches).T.sum(axis=1).to_frame('Matches')
      
      df = df.join(matches_df)
      

      输出

                                        Product Description   Matches
      0    UNDER ARMOUR LADIES FLY-BY STRETCH MESH TANK TOP  Tank Top
      1         UNDER ARMOUR LADIES SPEEDFORM NO SHOW SOCKS     Socks
      2         UNDER ARMOUR LADIES SPEEDFORM NO SHOW SOCKS     Socks
      3                  UNDER ARMOUR LADIES PLAY UP SHORTS          
      4          REEBOK LADIES CLASSIC LEATHER MID TRAINERS  Trainers
      5   UNDER ARMOUR MENS Spring Performance Oxford SHIRT   T-Shirt
      6    UNDER ARMOUR LADIES HEATGEAR ALPHA SHORTY SHORTS          
      7                              ADIDAS LADIES PRO TANK  Tank Top
      8             REEBOK LADIES ONE SERIES V NECK T-SHIRT   T-Shirt
      9                           REEBOK LADIES DF LONG BRA          
      10                  NIKE LADIES BASELINE TENNIS SKIRT          
      11           UNDER ARMOUR MENS ESCAPE 7" SOLID SHORTS       Hat
      12   UNDER ARMOUR LADIES FLY-BY STRETCH MESH TANK TOP  Tank Top
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-04
        • 1970-01-01
        • 1970-01-01
        • 2020-07-07
        • 1970-01-01
        • 2018-03-06
        相关资源
        最近更新 更多