基于Pandas GroupBy按分组条件计算类别平均价格
解决方案
1. 生成可复现的模拟数据
用pandas和numpy生成符合需求的测试数据,包含3个类别,其中A类20条数据,B、C类各150条,同时给B、C类加入少量异常值方便验证过滤逻辑:
import pandas as pd import numpy as np # 设置随机种子保证可复现 np.random.seed(42) # 生成各类别数据 data = [] # A类:20条,价格服从正态分布 data.extend([("A", np.random.normal(50, 10)) for _ in range(20)]) # B类:150条,正常价格+3个异常值 b_prices = list(np.random.normal(60, 12, 147)) + [150, -20, 160] data.extend([("B", p) for p in b_prices]) # C类:150条,正常价格+2个异常值 c_prices = list(np.random.normal(45, 8, 148)) + [100, -10] data.extend([("C", p) for p in c_prices]) # 转为DataFrame df = pd.DataFrame(data, columns=["category", "price"])
2. 实现带条件的分组平均计算
通过自定义聚合函数结合groupby.apply()实现需求逻辑:
def conditional_mean(group): group_size = len(group) if group_size > 100: # 计算组内均值和标准差 mean_val = group.mean() std_val = group.std() # 过滤掉均值±3倍标准差外的数据 filtered = group[(group >= mean_val - 3*std_val) & (group <= mean_val + 3*std_val)] return filtered.mean() else: # 直接返回全部数据的均值 return group.mean() # 执行分组计算 result = df.groupby("category")["price"].apply(conditional_mean).reset_index(name="avg_price") print(result)
代码说明
- 自定义函数
conditional_mean接收每个分组的price序列,先判断分组大小:- 当分组行数>100时,先计算组内均值和标准差,过滤超出
均值±3σ的异常值后再求平均 - 当分组行数≤100时,直接返回所有数据的均值
- 当分组行数>100时,先计算组内均值和标准差,过滤超出
- 使用
groupby.apply()将函数应用到每个分组,最后用reset_index()整理结果格式
验证结果
运行代码后,B、C类的平均价格会排除掉预设的异常值,A类则直接使用全部数据计算均值,完全符合需求。
内容的提问来源于stack exchange,提问作者glpsx
相关产品推荐
相关产品推荐

