Pandas 动态聚合列
Pandas Aggregate columns dynamically
我的目标是聚合类似于 SAS 的“proc summary using types”的数据 我的起始 pandas 数据框可能看起来像这样,其中数据库已经完成了所有 dimensions/classification 变量的原始分组,并且对措施做了一些聚合功能。
所以在 sql 这看起来像
select gender, age, sum(height), sum(weight)
from db.table
group by gender, age
gender
age
height
weight
F
19
70
123
M
24
72
172
然后我想使用 pandas 来汇总数据,根据不同的分组依据计算汇总行来得出这个结果。
gender
age
height
weight
.
.
142
295
.
19
70
123
.
24
72
172
F
.
70
123
M
.
72
172
F
19
70
123
M
24
72
172
其中第一行是没有分组依据的 agg
第 2 行和第 3 行按年龄分组
4 和 5 只按性别分类
然后只是正常的行
我当前的代码如下所示
# normally dynamic just hard coded for this example
measures = {'height':{'stat':'sum'}, 'age':{'stat':'sum'}}
msr_config_dict = {}
for measure in measures:
if measure in message_measures:
stat = measures[measure]['stat']
msr_config_dict[measure] = pd.NamedAgg(measure, stat)
# compute agg with no group by as starting point
df=self.df.agg(**msr_config_dict)
dimensions = ['gender','age'] # also dimensions is dynamic in real life
dim_vars = []
for dim in dimensions:
dim_vars.append(dim)
if len(dim_vars) > 1:
# compute agg of compound dimensions
df_temp = self.df.groupby(dim_vars, as_index=False).agg(msr_config_dict)
df = df.append(df_temp, ignore_index=True)
# always compute agg of solo dimension
df_temp = self.df.groupby(dim, as_index=False).agg(msr_config_dict)
df = df.append(df_temp, ignore_index=True)
使用此代码我得到 AttributeError: 'height' is not a valid function for 'Series' object
agg函数的输入我也试过了
{'height':[('height', 'sum')], 'weight':[('weight', 'sum')]} 我正在尝试计算所有高度的总和并命名输出高度。这也有一个属性错误。
我知道我只会为每个度量计算一个聚合函数,所以我想动态构建 pandas 聚合函数的输入,并始终将统计重命名为自身,这样我就可以将它附加到我所在的数据框使用摘要行构建。
我是 SAS 背景的 pandas 新手。
任何帮助将不胜感激。
IIUC:
cols = ['height', 'weight']
out = pd.concat([df[cols].sum(0).to_frame().T,
df.groupby('age')[cols].sum().reset_index(),
df.groupby('gender')[cols].sum().reset_index(),
df], ignore_index=True)[df.columns].fillna('.')
输出:
>>> out
gender age height weight
0 . . 142 295
1 . 19.0 70 123
2 . 24.0 72 172
3 F . 70 123
4 M . 72 172
5 F 19.0 70 123
6 M 24.0 72 172
这里有一个更灵活的解决方案,它扩展了 . You can use itertools.combinations 的解决方案以创建所有尺寸组合和所有可能的组合长度。
from itertools import combinations
# your input
measures = {'height':{'stat':'sum'}, 'weight':{'stat':'min'}}
dimensions = ['gender','age']
# change the nested dictionary
msr_config_dict = {key:val['stat'] for key, val in measures.items()}
# concat all possible aggregation
res = pd.concat(
# case with all aggregated
[df.agg(msr_config_dict).to_frame().T]
# cases at least one column to aggregate over
+ [df.groupby(list(_dimCols)).agg(msr_config_dict).reset_index()
# for combinations of length 1, 2.. depending on the number of dimensions
for nb_cols in range(1, len(dimensions))
# all combinations of the specific lenght
for _dimCols in combinations(dimensions, nb_cols)]
# original dataframe
+ [df],
ignore_index=True)[df.columns].fillna('.')
print(res)
# gender age height weight
# 0 . . 142 123
# 1 F . 70 123
# 2 M . 72 172
# 3 . 19.0 70 123
# 4 . 24.0 72 172
# 5 F 19.0 70 123
# 6 M 24.0 72 172
我的目标是聚合类似于 SAS 的“proc summary using types”的数据 我的起始 pandas 数据框可能看起来像这样,其中数据库已经完成了所有 dimensions/classification 变量的原始分组,并且对措施做了一些聚合功能。 所以在 sql 这看起来像
select gender, age, sum(height), sum(weight)
from db.table
group by gender, age
gender | age | height | weight |
---|---|---|---|
F | 19 | 70 | 123 |
M | 24 | 72 | 172 |
然后我想使用 pandas 来汇总数据,根据不同的分组依据计算汇总行来得出这个结果。
gender | age | height | weight |
---|---|---|---|
. | . | 142 | 295 |
. | 19 | 70 | 123 |
. | 24 | 72 | 172 |
F | . | 70 | 123 |
M | . | 72 | 172 |
F | 19 | 70 | 123 |
M | 24 | 72 | 172 |
其中第一行是没有分组依据的 agg 第 2 行和第 3 行按年龄分组 4 和 5 只按性别分类 然后只是正常的行
我当前的代码如下所示
# normally dynamic just hard coded for this example
measures = {'height':{'stat':'sum'}, 'age':{'stat':'sum'}}
msr_config_dict = {}
for measure in measures:
if measure in message_measures:
stat = measures[measure]['stat']
msr_config_dict[measure] = pd.NamedAgg(measure, stat)
# compute agg with no group by as starting point
df=self.df.agg(**msr_config_dict)
dimensions = ['gender','age'] # also dimensions is dynamic in real life
dim_vars = []
for dim in dimensions:
dim_vars.append(dim)
if len(dim_vars) > 1:
# compute agg of compound dimensions
df_temp = self.df.groupby(dim_vars, as_index=False).agg(msr_config_dict)
df = df.append(df_temp, ignore_index=True)
# always compute agg of solo dimension
df_temp = self.df.groupby(dim, as_index=False).agg(msr_config_dict)
df = df.append(df_temp, ignore_index=True)
使用此代码我得到 AttributeError: 'height' is not a valid function for 'Series' object
agg函数的输入我也试过了 {'height':[('height', 'sum')], 'weight':[('weight', 'sum')]} 我正在尝试计算所有高度的总和并命名输出高度。这也有一个属性错误。 我知道我只会为每个度量计算一个聚合函数,所以我想动态构建 pandas 聚合函数的输入,并始终将统计重命名为自身,这样我就可以将它附加到我所在的数据框使用摘要行构建。
我是 SAS 背景的 pandas 新手。 任何帮助将不胜感激。
IIUC:
cols = ['height', 'weight']
out = pd.concat([df[cols].sum(0).to_frame().T,
df.groupby('age')[cols].sum().reset_index(),
df.groupby('gender')[cols].sum().reset_index(),
df], ignore_index=True)[df.columns].fillna('.')
输出:
>>> out
gender age height weight
0 . . 142 295
1 . 19.0 70 123
2 . 24.0 72 172
3 F . 70 123
4 M . 72 172
5 F 19.0 70 123
6 M 24.0 72 172
这里有一个更灵活的解决方案,它扩展了
from itertools import combinations
# your input
measures = {'height':{'stat':'sum'}, 'weight':{'stat':'min'}}
dimensions = ['gender','age']
# change the nested dictionary
msr_config_dict = {key:val['stat'] for key, val in measures.items()}
# concat all possible aggregation
res = pd.concat(
# case with all aggregated
[df.agg(msr_config_dict).to_frame().T]
# cases at least one column to aggregate over
+ [df.groupby(list(_dimCols)).agg(msr_config_dict).reset_index()
# for combinations of length 1, 2.. depending on the number of dimensions
for nb_cols in range(1, len(dimensions))
# all combinations of the specific lenght
for _dimCols in combinations(dimensions, nb_cols)]
# original dataframe
+ [df],
ignore_index=True)[df.columns].fillna('.')
print(res)
# gender age height weight
# 0 . . 142 123
# 1 F . 70 123
# 2 M . 72 172
# 3 . 19.0 70 123
# 4 . 24.0 72 172
# 5 F 19.0 70 123
# 6 M 24.0 72 172