条件下按列分组计算平均值

Group by columns under conditions to calculate average

我有一个 raw 数据集,如下所示:

ColA ColB duration interval Counter
A SD 2 4 1
A SD 3 3 2
A UD 2 1 10
B UD 1 2 2
B UD 2 2 2
B SD 3 3 13
B SD 1 4 19

我期待 输出结果 如下所示:

输出解释:

  1. SumCounter 是按 ColA 和 ColB 值计算的组中计数器值的总和。
  2. AvgdurationSD/UD 和 AvgIntervalSD/UD 是通过对 ColA 和 ColB 取平均值并具有 0 值来创建的,以防列不符合条件(例如,AvgDurationSD 和 AvIntervalSD 对于一组ColA = A 和 ColB = UD。

我知道我必须使用 group byagg 函数才能在此处应用,但我不太确定如何在各个新列上应用 ColB 的条件。

感谢任何帮助:)

DataFrame.pivot_table与辅助列new一起使用,像ColB一样复制,然后展平MultiIndex并将输出添加到聚合sum创建的新DataFrame:

df1 = (df.assign(new=df['ColB'])
         .pivot_table(index=['ColA', 'ColB'], 
                      columns='new', 
                      values=['interval','duration'], 
                      fill_value=0,
                      aggfunc='mean'))
df1.columns = df1.columns.map(lambda x: f'{x[0]}{x[1]}')
df = (df.groupby(['ColA','ColB'])['Counter']
        .sum()
        .to_frame(name='SumCounter')
        .join(df1).reset_index())
print (df)
  ColA ColB  SumCounter  durationSD  durationUD  intervalSD  intervalUD
0    A   SD           3         2.5         0.0         3.5           0
1    A   UD          10         0.0         2.0         0.0           1
2    B   SD          32         2.0         0.0         3.5           0
3    B   UD           4         0.0         1.5         0.0           2

您可以使用 Named Aggregation

按列 A 和按列 B 分组
out = df.groupby('ColA').apply(lambda g: g.groupby('ColB').agg({'duration': [(f'{g["ColB"].iloc[0]}', 'mean')],
                                                                'interval': [(f'{g["ColB"].iloc[0]}', 'mean')],
                                                                'Counter': 'sum'})).fillna(0)
print(out)

          duration interval Counter duration interval
                SD       SD     sum       UD       UD
ColA ColB
A    SD        2.5      3.5       3      0.0      0.0
     UD        2.0      1.0      10      0.0      0.0
B    SD        0.0      0.0      32      2.0      3.5
     UD        0.0      0.0       4      1.5      2.0

然后重命名多索引列

out.columns = ['SumCounter' if 'Counter' in col[0] else f'Avg{col[0]}{col[1]}' for col in out.columns.values]
print(out)

           AvgdurationSD  AvgintervalSD  SumCounter  AvgdurationUD  AvgintervalUD
ColA ColB
A    SD              2.5            3.5           3            0.0            0.0
     UD              2.0            1.0          10            0.0            0.0
B    SD              0.0            0.0          32            2.0            3.5
     UD              0.0            0.0           4            1.5            2.0

groupby 的一个选项:


temp = (df
        .assign(dummy = df.ColB)
        .groupby(['ColA','ColB','dummy'])
        .agg({'duration':'mean', 'interval':'mean', 'Counter':'sum'})
        .rename(columns = {'Counter':'SumCounter'})
        .set_index('SumCounter', append = True)
        .unstack('dummy', fill_value = 0)
        )

temp.columns = temp.columns.map(lambda x: f"Avg{''.join(x)}")

temp.reset_index()

  ColA ColB  SumCounter  AvgdurationSD  AvgdurationUD  AvgintervalSD  AvgintervalUD
0    A   SD           3            2.5            0.0            3.5            0.0
1    A   UD          10            0.0            2.0            0.0            1.0
2    B   SD          32            2.0            0.0            3.5            0.0
3    B   UD           4            0.0            1.5            0.0            2.0