条件下按列分组计算平均值
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
我期待 输出结果 如下所示:
输出解释:
- SumCounter 是按 ColA 和 ColB 值计算的组中计数器值的总和。
- AvgdurationSD/UD 和 AvgIntervalSD/UD 是通过对 ColA 和 ColB 取平均值并具有 0 值来创建的,以防列不符合条件(例如,AvgDurationSD 和 AvIntervalSD 对于一组ColA = A 和 ColB = UD。
我知道我必须使用 group by
和 agg
函数才能在此处应用,但我不太确定如何在各个新列上应用 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
我有一个 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 |
我期待 输出结果 如下所示:
输出解释:
- SumCounter 是按 ColA 和 ColB 值计算的组中计数器值的总和。
- AvgdurationSD/UD 和 AvgIntervalSD/UD 是通过对 ColA 和 ColB 取平均值并具有 0 值来创建的,以防列不符合条件(例如,AvgDurationSD 和 AvIntervalSD 对于一组ColA = A 和 ColB = UD。
我知道我必须使用 group by
和 agg
函数才能在此处应用,但我不太确定如何在各个新列上应用 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