如何在Pandas中使用groupby.agg()计算分组分位数?
使用Pandas groupby.agg一次性聚合统计量与自定义分位数
最优实现方案
直接构建包含所有聚合规则的字典,一次性完成常规统计量和分位数的计算,同时自动生成指定格式的列名:
import numpy as np import pandas as pd from functools import partial rng = np.random.default_rng(seed=18860504) df = pd.DataFrame({ "dummy": 1, "bell": rng.normal(loc=0, scale=1, size=100), "fish": rng.poisson(lam=10, size=100), "cabin": rng.lognormal(mean=0, sigma=1.0, size=100), }) quants = [x/5 for x in range(6)] # 构建聚合字典:包含常规统计量+自定义分位数 agg_dict = { # 常规统计指标 "bell_mean": ("bell", "mean"), "bell_median": ("bell", "median"), "fish_mean": ("fish", "mean"), "fish_median": ("fish", "median"), } # 批量添加分位数聚合项 for q in quants: q_str = f"{int(100*q):03d}" # 使用partial绑定分位数参数,避免lambda的变量捕获问题 agg_dict[f"bell_q{q_str}"] = ("bell", partial(pd.Series.quantile, q=q)) agg_dict[f"fish_q{q_str}"] = ("fish", partial(pd.Series.quantile, q=q)) # 执行一次groupby聚合,直接得到最终结果 result = df.groupby("dummy").agg(**agg_dict) print(result)
为什么之前的写法无效
你尝试的几种agg语法失败的原因:
"quantile(0.1)"是字符串格式,Pandas仅识别内置统计函数的纯名称,不会解析带参数的字符串;("fish", "quantile", 0.1)会把0.1传递给quantile的第二个参数(interpolation插值方式),而非分位数q的值,不符合预期;- 带参数的函数需要通过参数绑定的方式传递给
agg,比如用functools.partial或带默认参数的lambda。
替代方案:用lambda绑定参数
如果不想引入functools.partial,也可以用lambda函数绑定分位数参数(注意要给lambda的参数设置默认值,避免循环变量捕获问题):
agg_dict = { "bell_mean": ("bell", "mean"), "bell_median": ("bell", "median"), "fish_mean": ("fish", "mean"), "fish_median": ("fish", "median"), } for q in quants: q_str = f"{int(100*q):03d}" agg_dict[f"bell_q{q_str}"] = ("bell", lambda x, q=q: x.quantile(q)) agg_dict[f"fish_q{q_str}"] = ("fish", lambda x, q=q: x.quantile(q)) result = df.groupby("dummy").agg(**agg_dict)
方案优势
相比你之前的循环拼接方法,这个方案:
- 仅执行一次groupby操作,计算效率更高,尤其是处理大数据集时;
- 代码更整洁,所有聚合规则集中定义,可读性和维护性更好;
- 直接生成目标格式的列名,无需后续重命名或拼接操作。
内容的提问来源于stack exchange,提问作者flies
相关产品推荐
相关产品推荐

