有条件地在groupby聚合函数中连接字符串

时间:2019-12-20 09:34:23

标签: python pandas dataframe

我有一个数据集,需要在单个字段上进行分组并在多个字段上进行汇总。作为聚合的一部分,我需要有条件地按排序顺序连接字符串列值。

输入:

SYSTIME             TT  REC TABLE   cat_a   cat_b   cat_c
01/11/2019 00:00    2   102 A       1       0       0
01/11/2019 00:00    2   103 B       1       0       0
01/11/2019 00:00    2   150 C       0       1       0
01/11/2019 00:01    3   200 B       1       0       0
01/11/2019 00:01    3   150 A       1       0       0
01/11/2019 00:01    3   104 D       0       0       1
01/11/2019 00:02    4   200 F       1       0       0
01/11/2019 00:02    5   250 A       1       0       0
01/11/2019 00:02    2   120 C       0       1       0
01/11/2019 00:02    3   150 E       1       0       0

预期输出:

SYSTIME             TT  REC TABLE   cat_a   cat_b   cat_c
01/11/2019 00:00    2   355 A;B     2       1       0
01/11/2019 00:01    3   454 A;B     2       0       1
01/11/2019 00:02    5   520 A;E;F   3       1       0

我有以下代码:

df_table_acc=df.groupby(['SYSTIME'],as_index=False).agg({'TT' : 'max','REC' : 'sum','TABLE': ';'.join, 'cat_a': 'sum', 'cat_b': 'sum', 'cat_c': 'sum'})

问题在于字符串连接,我想将cat_a = 1的TABLE值也连接在一起,还要排序。 目前,我在00:00分钟收到A; B; C,但只希望cat; a = 1

的A; B

是否可以向联接函数添加条件?

P.S:我是python的新手,我确实看到了类似的问题,但是我想专门在agg函数中添加条件

2 个答案:

答案 0 :(得分:1)

我找不到在agg中执行此操作的方法,因此,如果有人愿意请说。

不过,它很容易在agg之外使用,

df_table_acc=df.groupby(['SYSTIME'],as_index=False).agg(    #Remove TABLE from first agg
            {'TT' : 'max','REC' : 'sum', 'cat_a': 'sum', 'cat_b': 'sum', 'cat_c': 'sum'})
df_table_acc = pd.merge(df_table_acc, df[df['cat_a']>0].copy().groupby(['SYSTIME'],as_index=False).agg(
            {'TABLE':';'.join}),how='left',on='SYSTIME')

已针对索引问题进行了编辑。现在,我们在merge上使用SYSTIME以确保TABLESYSTIME

匹配

或者,通过更改数据,之后进行一些清理(编辑:修复了这一部分并增加了更好的分离)

import re
df['TABLE'] = df.apply(lambda x: x['TABLE'] if x['cat_a']>0 else '', axis=1)
df_table_acc=df.groupby(['SYSTIME'],as_index=False).agg(
            {'TT' : 'max','REC' : 'sum','TABLE': ';'.join, 
             'cat_a': 'sum', 'cat_b': 'sum', 'cat_c': 'sum'})
df_table_acc.TABLE = df_table_acc.TABLE.apply(lambda x: re.sub(';+',';',x).strip(';'))
#Quick explanation: the re part avoids having repeat ";" eg: "A;;C;D;;G" -> "A;C;D;G"
#The strip removes outside strings eg: ";A;B;" -> "A;B"

在使用第二种方法之前,请确保不需要其他任何TABLE列,或者使用诸如TABLE2之类的虚拟列。

答案 1 :(得分:0)

可以通过在应用groupby和agg之前过滤数据来解决您的问题

function。只需在使用此代码之前添加df=df[df['cat_a']==1].sort_values('TABLE')

df_table_acc = df.groupby(['SYSTIME'],as_index = False).agg({'TT':'max','REC':'sum','TABLE':';'。join,' cat_a':'sum','cat_b':'sum','cat_c':'sum'})