如何根据部分字符串匹配添加大熊猫列?

时间:2020-07-11 20:07:38

标签: python pandas

我有一个熊猫数据框,其中包含各种尚未定义的类别(天然气,杂货,快餐等)的信用卡费用。

df1: 

Category   Date         Description                 Cost 
nan        7.1.20       Chipotle Downtown West      $8.23
nan        7.1.20       Break Time - Springfield    $23.57
nan        7.3.20       State Farm - Agent          $94.23
nan        7.3.20       T-Mobile                    $132.42
nan        7.4.20       Venmo -xj8382dzavvd         $8.00
nan        7.6.20       Broadway McDonald's         $11.73
nan        7.8.20       Break Time - Townsville     $44.23

我想维护第二个数据框,该数据框在描述中搜索关键字并填充“类别”(Category)列。如下:

df2:

item           category
mcdonald       fast food
state farm     insurance
break time     gas
chipotle       fast food
mobile         cell phone 

这里的想法是,我将编写代码行以在df1['Description']中搜索部分字符串,并用df1['Category']中的值填充df2[category]

我敢肯定有一种干净而pythonic的方式来处理此代码,但是下面是我能得到的最接近的方法。以下代码的错误结果是,包含匹配项的df1['Category']的所有行都设置为df2中的最后一个循环(例如,在这种情况下,所有行都将设置为“手机”)。

    for x in df2['item']:
        for y in df2['category']:
            df1['Category'] = np.where(
                        df1['Description'].str.lower().str.contains(x),
                        y,
                        df1['Category'])

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您可以使用map,Python的内置difflib获取紧密匹配功能以及lambda表达式。 difflib调用返回一个字符串匹配列表,您可以根据需要调整截止参数以获得或多或少的灵敏度。

import difflib

# you'll need to change both cutoff values here for the lambda to work correctly

df1['Category'] = df1['Description'].map(lambda x: difflib.get_close_matches(x, df2['item'], cutoff=0.3)[0] if len(difflib.get_close_matches(x, df2['item'], cutoff=0.3)) > 1 else 'no match')

print(df1)


    Category    Date    Description                 Cost
0   chipotle    7.1.20  Chipotle Downtown West      $8.23
1   break time  7.1.20  Break Time - Springfield    $23.57
2   state farm  7.3.20  State Farm - Agent          $94.23
3   mobile      7.3.20  T-Mobile                    $132.42
4   no match    7.4.20  Venmo -xj8382dzavvd         $8.00
5   mcdonald    7.6.20  Broadway McDonald's         $11.73
6   break time  7.8.20  Break Time - Townsville     $44.23