首页 > 解决方案 > 在 groupby 聚合函数中有条件地连接字符串

问题描述

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

输入:

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 值并排序。目前我得到 A;B;C 分钟 00:00 但只期望 A;B 其中 cat_a=1

有没有办法给join函数添加条件?

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

标签: pythonpandasdataframe

解决方案


我无法找到一种方法来做到这一点,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')

这是针对索引问题进行编辑的。我们现在使用mergeonSYSTIME来确保TABLE匹配SYSTIME

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

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


推荐阅读