【问题标题】:Pandas categorize a dataframe based on another dataframe with substringsPandas 根据另一个带有子字符串的数据框对数据框进行分类
【发布时间】:2021-12-31 14:46:11
【问题描述】:

我正在尝试学习 pandas 和 python 以将一些问题从 excel 转移到 pandas/python。我的银行有一个包含 10000 多条记录的大 csv 文件。我想根据描述对记录进行分类。为此,我有一个带有关键字的大映射文件。在 excel 中,我使用了 vLookup,我正在尝试将此解决方案融入 Pandas/python

所以我可以将 csv 读入数据帧 dfMain。一列(在 dfMain 中)带有名为 description 的文本,供我输入以根据名为 dfMap 的映射文件对其进行分类。

dfMain 看起来像这样简化:

Datum       Bedrag  Description     
2020-01-01  -166.47 een cirkel voor je uit
2020-01-02  -171.79 even een borreling
2020-01-02  -16.52  stilte zacht geluid
2020-01-02  -62.88  een steentje in het water
2020-01-02  -30.32  gooi jij je zorgen weg
2020-01-02  -45.99  dan ben je laf weet je dat
2020-01-02  -322.44 je klaagt ook altijd over pech
2020-01-03  -4.80   jij kan niet ophouden zorgen
2020-01-07  5.00    de wereld te besnauwen

dfMap 看起来像这样简化

    sleutel     code
0   borreling   A1
1   zorgen      B2
2   steentje    C2
3   een         C1

dfMap 包含关键字('sleutel')和类别代码('code')。

当 'sleutel' 是 dfMain 中 'description' 的子字符串时,在 dfMain 中将额外添加一个名为 'category' 的列将获取代码的值。 我知道多个关键字可以应用于某些描述值,但先到先得,换句话说:dfMain 中的行数必须保持不变。

生成的数据框必须如下所示:

Out[34]:

Datum        Bedrag Description                     category        
2020-01-01  -166.47 een cirkel voor je uit          C1
2020-01-02  -171.79 even een borreling              A1
2020-01-02  -16.52  stilte zacht geluid             NaN
2020-01-02  -62.88  een steentje in het water       C2
2020-01-02  -30.32  gooi jij je zorgen weg          B2
2020-01-02  -45.99  dan ben je laf weet je dat      NaN
2020-01-02  -322.44 je klaagt ook altijd over pech  NaN
2020-01-03  -4.80   jij kan niet ophouden zorgen    B2
2020-01-07  5.00    de wereld te besnauwen          NaN
 

我尝试了很多关于 join 的操作,但无法正常工作。

【问题讨论】:

  • 您的“先到先得”规则令人困惑。在“even een borreling”中,“een”是第一位的,对吧?
  • 是的,你是对的,这令人困惑。底线是一旦给出一个类别就不会再次访问它,即行数保持不变。在我的主要数据中,发生这种情况的可能性非常小

标签: python pandas pandas-groupby


【解决方案1】:

一个有效的解决方案是使用带有extract 的正则表达式,然后使用map 得到结果:

regex = '(%s)' % dfMap['sleutel'].str.cat(sep='|')

dfMain['category'] = (
 dfMain['Description']
   .str.extract(regex, expand=False)
   .map(dfMap.set_index('sleutel')['code'])
 )

输出:

        Datum  Bedrag                     Description category
0  2020-01-01 -166.47          een cirkel voor je uit       C1
1  2020-01-02 -171.79              even een borreling       C1
2  2020-01-02  -16.52             stilte zacht geluid      NaN
3  2020-01-02  -62.88       een steentje in het water       C1
4  2020-01-02  -30.32          gooi jij je zorgen weg       B2
5  2020-01-02  -45.99      dan ben je laf weet je dat      NaN
6  2020-01-02 -322.44  je klaagt ook altijd over pech      NaN
7  2020-01-03   -4.80    jij kan niet ophouden zorgen       B2
8  2020-01-07    5.00          de wereld te besnauwen      NaN

生成的正则表达式最终将成为'(borreling|zorgen|steentje|een)'

【讨论】:

  • 我印象深刻,谢谢。这肯定适用于我的示例。但我无法让它在我原来的大型数据框上工作。我收到一个错误,说明没有看到系列。
  • 你能提供确切的错误信息和回溯吗?
【解决方案2】:

试试这个:

import pandas as pd

# prepare the data

Datum = ['2020-01-01', '2020-01-02', '2020-01-02', '2020-01-02', '2020-01-02', '2020-01-02', '2020-01-02', '2020-01-03', '2020-01-03']
Bedrag = [-166.47, -171.79, -16.52, -62.88, -30.32, -45.99, -322.44, -4.80, 5.00]
Description = ["een cirkel voor je uit", "even een borreling", "stilte zacht geluid", "een steentje in het water",
               "gooi jij je zorgen weg", "dan ben je laf weet je dat", "je klaagt ook altijd over pech", "jij kan niet ophouden zorgen", "de wereld te besnauwen"]

dfMain = pd.DataFrame(Datum, columns=['Datum'])
dfMain['Bedrag'] = Bedrag
dfMain['Description'] = Description

sleutel = ["borreling", "zorgen", "steentje", "een"]
code = ["A1", "B2", "C2", "C1"]

dfMap = pd.DataFrame(sleutel, columns=['sleutel'])
dfMap['code'] = code
print(dfMap)
# solution

map_code = pd.Series(dfMap.code.values ,index=dfMap.sleutel).to_dict()


def extract_codes(row):
    for item in map_code:
        if item in row:
            return map_code[item]
    return "NaN"

dfMain['category'] = dfMain['Description'].apply(extract_codes)

print(dfMain)

【讨论】:

  • 谢谢,Tomer S。这很好用,它对我的​​原始数据很有效。感谢大家的快速和良好的答案
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 2022-01-01
  • 2022-08-03
  • 2022-08-21
  • 1970-01-01
  • 2018-01-16
  • 1970-01-01
  • 2016-12-15
相关资源
最近更新 更多