【问题标题】:Credit Card Transaction Classification in PythonPython中的信用卡交易分类
【发布时间】:2021-06-09 15:38:48
【问题描述】:

我很想知道是否有人对如何在 Python 中使用 Pandas 完成此任务有任何想法。

我有一个数据框 (df1),其中包含信用卡交易详情,其中包含销售点描述 (df1['Description']) 和金额 (df1['amount'])。每个位置的 POS 描述都是唯一的,因此您最终会得到多个关于 Amazon、Shell Oil 等的描述。

我有另一个数据框 (df_lookup) 将用作查找表来对事务进行分类。此数据框将包含名称 (df_lookup['Name']) 和用于对每个事务进行分类的类别 df_lookup['Category'])。

这是我想要完成的: 比较 df1['Description'] 和 df_lookup['Name']。如果 df1['Description'] 包含 df_lookup['Name'],则相应的 df_lookup['Category'] 将作为新列 df1['Category'] 添加到 df1。请在下面查看每个数据框的示例和所需的结果。

df1 示例:

Description Amount
AMAZON.COM*ajlja09ja AMZN.COM 10
AMZN Mktp US *ajlkadf 15
AMZN Prime *an9adjah 20
Shell Oil 4106541031 20
Shell Oil 4163046510 25

df_lookup 示例:

Name Category
AMAZON Amazon
AMZN Amazon
Shell Oil Gas

想要的输出到 df1:

Description Amount Category
AMAZON.COM*ajlja09ja AMZN.COM 10 Amazon
AMZN Mktp US *ajlkadf 15 Amazon
AMZN Prime *an9adjah 20 Amazon
Shell Oil 4106541031 20 Gas
Shell Oil 4163046510 25 Gas

【问题讨论】:

  • 不要粗鲁,但你在上一个 DataFrame 中拼错了类别
  • 大声笑,文字很难!谢谢
  • yw pardner @bbalch

标签: python pandas dataframe


【解决方案1】:

我想出了一个解决方案,但大型 DataFrame 可能需要很长时间:

def func(x):
    global df_lookup
    for i in df_lookup['Name'].values:
        if i in x:
            return df_lookup.loc[df_lookup['Name'] == i, 'Category'].values[0]
    df_lookup = df_lookup.append({'Name': x, 'Category': 'Needs Category'}, ignore_index=True)
    return 'Needs Category'

df1['Category'] = df1['Description'].apply(lambda x: func(x))

如果您有 df_lookup 中没有类别的数据,例如GOOGLE 5555555555,那么你会得到以下输出。

df1 的输出:

                     Description  Amount        Category
0  AMAZON.COM*ajlja09ja AMZN.COM      10          Amazon
1          AMZN Mktp US *ajlkadf      15          Amazon
2           AMZN Prime *an9adjah      20          Amazon
3           Shell Oil 4106541031      20             Gas
4           Shell Oil 4163046510      25             Gas
5                 GOOGLE 5555555      10  Needs Category

df_lookup 的输出:

             Name        Category
0          AMAZON          Amazon
1            AMZN          Amazon
2       Shell Oil             Gas
3  GOOGLE 5555555  Needs Category

使用此代码,您可以为df1 中的每一行迭代df_lookup,因此对于df_lookup 中的大量类别,这不是最有效的方法

【讨论】:

  • 谢谢,太好了!一个后续问题。如果我指定“需要类别”以在未找到类别的情况下返回。有没有办法附加 df_lookup 以将这些行包含在 df1['Description'] 和 df1['Cateogry'] (在这种情况下为“需要类别”)
  • @bbalch 我已经编辑了函数以添加未找到的类别
  • 这非常有效。在使用了一点之后,我想了解您对额外增强功能的看法。这当前基于 [‘Name’] 进行查找并返回相应的 [‘Category’]。有没有办法修改它,以便它根据 [‘Name’] 和 [‘Account’] 进行查找?假设 [‘Account’] 列同时添加到 df1 和 df_lookup DataFrames。 @99_m4n
【解决方案2】:

您可以尝试以下方法。它创建了一个Series,其中包含所有匹配类别的集合(如果没有匹配则为空,如果有多个匹配则为多个值)。有一个显式循环,但它在查找表上(大概比df1,要分类的DataFrame 小得多):

result = pd.Series([set()] * len(df1), index=df1.index, name='Categories')
dstr = df1['Description'].str
for k, name in df_lookup.set_index('Category')['Name'].items():
    idx = dstr.contains(name)
    result.loc[idx] = result.loc[idx].apply(lambda s: s|{k})

您可以将其分配给df1 的新列,或以您喜欢的任何方式使用它。

关于你的例子:

>>> df1.assign(categories=result)
                     Description  Amount categories
0  AMAZON.COM*ajlja09ja AMZN.COM      10   {Amazon}
1          AMZN Mktp US *ajlkadf      15   {Amazon}
2           AMZN Prime *an9adjah      20   {Amazon}
3           Shell Oil 4106541031      20      {Gas}
4           Shell Oil 4163046510      25      {Gas}

【讨论】:

  • 谢谢,太好了!
  • 确定;如果df1 大于df_lookup,它应该是迄今为止最快的解决方案(因为Python 循环在后者,而不是前者)。它还可以处理您可能有 0 个匹配项或超过 1 个匹配项的两种情况。
猜你喜欢
  • 2014-11-06
  • 1970-01-01
  • 2012-07-22
  • 2011-02-22
  • 2012-07-03
  • 2012-08-13
  • 2011-09-03
  • 1970-01-01
相关资源
最近更新 更多