首页 > 解决方案 > 在Python中每组每3行分组和求和

问题描述

我有一个数据框 df,我想在 Python 中对每组每 3 行进行分组和求和

数据

location    date    one         two         three
aa          Q4 16   1.444444    4.111111    2.444444
aa          Q4 16   1.611111    5.111111    2.777777
aa          Q4 16   2.111111    4.222222    2.999999
aa          Q4 23   2.444444    6.111111    2.444444
aa          Q4 23   3.611111    5.111111    2.777777
aa          Q4 23   1.111111    8.222222    1.999999
bb          Q1 24   0.111111    1.111111    1.111111
bb          Q1 24   2.111111    2.111111    2.111111
bb          Q1 24   3.122222    2.222222    1.999999

期望的

每 3 行分组和求和,确保每个位置都分组

location    date    one         two         three
aa          Q4 16   5.166666    13.44444    8.22222
aa          Q4 23   7.61111     19.55556    7.22222
bb          Q1 24   5.344444    5.444444    5.222221    

正在做

我正在设置我希望分组的号码,然后

N = 3
df.groupby(df.index // N).sum()

标签: pythonpandasnumpy

解决方案


在这种情况下,我们可以使用groupby agg并声明每个转换('first' 表示我们想要获取第一个实例的值,而 'sum' 表示剩余的值):

N = 3
res_df = df.groupby(df.index // N).agg({
    'location': 'first',
    'date': 'first',
    'one': 'sum',
    'two': 'sum',
    'three': 'sum'
})

如果需要对许多列求和,也可以通过编程方式构建聚合字典:

N = 3
first_cols = ['location', 'date']
res_df = df.groupby(df.index // N).agg({
    # Cols not to sum
    **{k: 'first' for k in first_cols},
    # Sum all other cols
    **{k: 'sum' for k in df.columns if k not in first_cols}
})

无论如何res_df是:

  location   date       one        two     three
0       aa  Q4 16  5.166666  13.444444  8.222220
1       aa  Q4 23  7.166666  19.444444  7.222220
2       bb  Q1 24  5.344444   5.444444  5.222221

假设我们不需要每三行,而只需要唯一的location date对。我们可以通过groupby设置sort=False来确保值按出现顺序出现:

res_df = df.groupby(['location', 'date'], as_index=False, sort=False).sum()

如果我们需要每组中的每三行,我们可以使用groupby cumcount,然后将每组分成 N 行的子组。droplevel这里需要删除最后一个索引级别groupby(通过创建子组添加):

N = 3
grp_cols = ['location', 'date']
res_df = df.groupby([
    *grp_cols, df.groupby(grp_cols).cumcount() // N
], sort=False).sum().droplevel(-1).reset_index()

使用此示例数据,这些选项也会产生相同的结果res_df

  location   date       one        two     three
0       aa  Q4 16  5.166666  13.444444  8.222220
1       aa  Q4 23  7.166666  19.444444  7.222220
2       bb  Q1 24  5.344444   5.444444  5.222221

设置:

import pandas as pd

df = pd.DataFrame({
    'location': ['aa', 'aa', 'aa', 'aa', 'aa', 'aa', 'bb', 'bb', 'bb'],
    'date': ['Q4 16', 'Q4 16', 'Q4 16', 'Q4 23', 'Q4 23', 'Q4 23', 'Q1 24',
             'Q1 24', 'Q1 24'],
    'one': [1.444444, 1.611111, 2.111111, 2.444444, 3.611111, 1.111111,
            0.111111, 2.111111, 3.122222],
    'two': [4.111111, 5.111111, 4.222222, 6.111111, 5.111111, 8.222222,
            1.111111, 2.111111, 2.222222],
    'three': [2.444444, 2.777777, 2.999999, 2.444444, 2.777777, 1.999999,
              1.111111, 2.111111, 1.999999]
})

推荐阅读