Groupby 并根据条件将多个组合并聚合为一个组
Groupby and combine and aggregate multiple groups into one single group based on condition
我有一个涉及多个顶级实体的分层时间序列 pandas DataFrame。我想合并和聚合少于 12 个数据点的系列(即 date
的计数少于 12)。将它们组合起来,这样我就可以拥有超过 12 个数据点,并聚合出现在相同 date
.
上的值
请注意,我不想合并属于不同 level0
组的那些,因为它们不相关(例如,A 和 Z 是两个不同的实体)。换句话说,我想对每个 level0
组内的 level2
进行组合和聚合。 groupby
之后的原始数据集是这样的:
grp = df.groupby(['level0','level1','level2','date']).sum() #sum the values within the same date
#because each level2 entity can have multiple records occurring on the same date
values
level0 level1 level2 date
A AA AA_1 2006-10-31 300 # assume AA_1 have more than 12 data points so I dont't want to modify
2006-11-30 220
2006-12-31 415
... ...
2007-04-30 19
2007-05-31 77
2007-08-31 463
AA_2 2006-04-30 600 # assume AA_2 has less than 12 data points
2006-05-31 2600
2007-09-30 6600
AB AB_1 2006-04-30 100 # assume AB_1 has less than 12 data points
2006-08-31 200
2007-06-30 300
2007-09-30 400
... ... ... ... ...
Z ZZ ZZ_9 2006-04-30 3680 # assume ZZ_9 has less than 12 data points
2006-09-30 277
2007-03-31 1490
2007-09-30 289
2007-10-31 387
我假设属于 A
组的 AA_2
和 AB_1
都少于 12 个数据点,所以我想将它们合并。他们有两个重复的日期,所以对于这两个日期,我想总结价值。得到新的层级组后,我也想把原来的去掉。
虽然ZZ_9
也有不到12个数据点,但我不会将其与其他两个合并,因为ZZ_9
属于组Z
!
期望的输出是这样的:
values
level0 level1 level2 date
A AA AA_1 2006-10-31 300
2006-11-30 220
2006-12-31 415
... ...
2007-04-30 19
2007-05-31 77
2007-08-31 463
agg_lv1 agg_lv2 2006-04-30 700 (=600+100) # assume we have more than 12 data points now
# as I don't want the code being lengthy
2006-05-31 2600
2006-08-31 200
... ...
2007-06-30 300
2007-09-30 7000 (=6600+400)
... ... ... ... ...
Z ZZ ZZ_9 2006-04-30 3680
2006-09-30 277
2007-03-31 1490
2007-09-30 289
2007-10-31 387
每个 level0
实体对于新的聚合级别(即 agg_lv1
和 agg_lv2
)具有相同的名称没关系,因为如上所述 level0
实体是不相关的我想保持命名简单。
如何做到这一点?
您可以分多个步骤完成此操作。首先将数据帧分成 2 个,其中第一个包含需要聚合的所有行(超过 12 个时间点和超过一个 level1
组)。
grp = grp.reset_index()
grp['nunique'] = grp.groupby(['level0'])['level1'].transform('nunique')
# partition
grp_small = grp.loc[grp['nunique'] > 1].groupby(['level0', 'level1', 'level2']).filter(lambda x: len(x) < 12)
idx_small = grp_small.index
grp_large = grp.loc[set(grp.index) - set(idx_small)]
现在我们可以在 grp_small
数据帧上应用 sum
聚合,同时保持 grp_large
不变。
grp_small = grp_small.groupby(['level0', 'date'], as_index=False).sum()
grp_small[['level1', 'level2']] = ['agg_lv1', 'agg_lv2']
最后,我们将两个数据帧连接在一起并应用一些最终的后处理:
df = pd.concat([grp_large, grp_small], ignore_index=True)
df = df.drop(columns='nunique').set_index(['level0', 'level1', 'level2', 'date']).sort_index()
给定数据的结果(在计算过程中向第一组添加了行):
values
level0 level1 level2 date
A AA AA_1 2006-10-31 300
2006-11-30 220
2006-12-31 415
... ...
2007-04-30 19
2007-05-31 77
2007-08-31 463
agg_lv1 agg_lv2 2006-04-30 700
2006-05-31 2600
2006-08-31 200
2007-06-30 300
2007-09-30 7000
... ... ... ... ...
Z ZZ ZZ_9 2006-04-30 3680
2006-09-30 277
2007-03-31 1490
2007-09-30 289
2007-10-31 387
我有一个涉及多个顶级实体的分层时间序列 pandas DataFrame。我想合并和聚合少于 12 个数据点的系列(即 date
的计数少于 12)。将它们组合起来,这样我就可以拥有超过 12 个数据点,并聚合出现在相同 date
.
请注意,我不想合并属于不同 level0
组的那些,因为它们不相关(例如,A 和 Z 是两个不同的实体)。换句话说,我想对每个 level0
组内的 level2
进行组合和聚合。 groupby
之后的原始数据集是这样的:
grp = df.groupby(['level0','level1','level2','date']).sum() #sum the values within the same date
#because each level2 entity can have multiple records occurring on the same date
values
level0 level1 level2 date
A AA AA_1 2006-10-31 300 # assume AA_1 have more than 12 data points so I dont't want to modify
2006-11-30 220
2006-12-31 415
... ...
2007-04-30 19
2007-05-31 77
2007-08-31 463
AA_2 2006-04-30 600 # assume AA_2 has less than 12 data points
2006-05-31 2600
2007-09-30 6600
AB AB_1 2006-04-30 100 # assume AB_1 has less than 12 data points
2006-08-31 200
2007-06-30 300
2007-09-30 400
... ... ... ... ...
Z ZZ ZZ_9 2006-04-30 3680 # assume ZZ_9 has less than 12 data points
2006-09-30 277
2007-03-31 1490
2007-09-30 289
2007-10-31 387
我假设属于 A
组的 AA_2
和 AB_1
都少于 12 个数据点,所以我想将它们合并。他们有两个重复的日期,所以对于这两个日期,我想总结价值。得到新的层级组后,我也想把原来的去掉。
虽然ZZ_9
也有不到12个数据点,但我不会将其与其他两个合并,因为ZZ_9
属于组Z
!
期望的输出是这样的:
values
level0 level1 level2 date
A AA AA_1 2006-10-31 300
2006-11-30 220
2006-12-31 415
... ...
2007-04-30 19
2007-05-31 77
2007-08-31 463
agg_lv1 agg_lv2 2006-04-30 700 (=600+100) # assume we have more than 12 data points now
# as I don't want the code being lengthy
2006-05-31 2600
2006-08-31 200
... ...
2007-06-30 300
2007-09-30 7000 (=6600+400)
... ... ... ... ...
Z ZZ ZZ_9 2006-04-30 3680
2006-09-30 277
2007-03-31 1490
2007-09-30 289
2007-10-31 387
每个 level0
实体对于新的聚合级别(即 agg_lv1
和 agg_lv2
)具有相同的名称没关系,因为如上所述 level0
实体是不相关的我想保持命名简单。
如何做到这一点?
您可以分多个步骤完成此操作。首先将数据帧分成 2 个,其中第一个包含需要聚合的所有行(超过 12 个时间点和超过一个 level1
组)。
grp = grp.reset_index()
grp['nunique'] = grp.groupby(['level0'])['level1'].transform('nunique')
# partition
grp_small = grp.loc[grp['nunique'] > 1].groupby(['level0', 'level1', 'level2']).filter(lambda x: len(x) < 12)
idx_small = grp_small.index
grp_large = grp.loc[set(grp.index) - set(idx_small)]
现在我们可以在 grp_small
数据帧上应用 sum
聚合,同时保持 grp_large
不变。
grp_small = grp_small.groupby(['level0', 'date'], as_index=False).sum()
grp_small[['level1', 'level2']] = ['agg_lv1', 'agg_lv2']
最后,我们将两个数据帧连接在一起并应用一些最终的后处理:
df = pd.concat([grp_large, grp_small], ignore_index=True)
df = df.drop(columns='nunique').set_index(['level0', 'level1', 'level2', 'date']).sort_index()
给定数据的结果(在计算过程中向第一组添加了行):
values
level0 level1 level2 date
A AA AA_1 2006-10-31 300
2006-11-30 220
2006-12-31 415
... ...
2007-04-30 19
2007-05-31 77
2007-08-31 463
agg_lv1 agg_lv2 2006-04-30 700
2006-05-31 2600
2006-08-31 200
2007-06-30 300
2007-09-30 7000
... ... ... ... ...
Z ZZ ZZ_9 2006-04-30 3680
2006-09-30 277
2007-03-31 1490
2007-09-30 289
2007-10-31 387