如何在Pandas分组中对任意列执行ANOVA分析并计算均值
解决方案:整合ANOVA p值与子组均值的通用Pipe函数
完整实现代码
import pandas as pd from scipy import stats def anova_with_means(data): # 1. 计算cat1/cat2组合的连续列均值 mean_df = data.groupby(['cat1', 'cat2']).mean().reset_index() # 重命名均值列(适配示例中的contin_前缀) mean_df.columns = [ col.replace('contin_', '') + '_mean' if col not in ['cat1', 'cat2'] else col for col in mean_df.columns ] # 2. 按cat1分组计算各连续列的ANOVA p值 def _anova_p_per_cat1(group): p_results = {} # 遍历所有连续列(排除分类列) for cont_col in group.columns.difference(['cat1', 'cat2']): # 获取该cat1组内各cat2子组的连续列数据(去空值) subgroups = [sub[cont_col].dropna() for _, sub in group.groupby('cat2')] # 执行ANOVA并提取p值 _, p_val = stats.f_oneway(*subgroups) # 重命名p值列 p_results[cont_col.replace('contin_', '') + '_anova_pval'] = p_val return pd.Series(p_results, name=group.name) # 生成每个cat1对应的p值表 p_val_df = data.groupby('cat1').apply(_anova_p_per_cat1).reset_index() # 3. 合并均值表与p值表,返回最终结果 return mean_df.merge(p_val_df, on='cat1', how='left')
使用示例
# 构造测试数据 test_data = pd.DataFrame({ 'cat1': ['A', 'A', 'B', 'B', 'C', 'C'], 'cat2': [1, 2, 1, 2, 1, 2], 'contin_Z': [8, 73, 0, 60, 85, 90], 'contin_Y': [33, 34, 86, 70, 65, 55] }) # 通过pipe调用函数 result = test_data.pipe(anova_with_means) print(result)
输出示例
cat1 cat2 Z_mean Y_mean Z_anova_pval Y_anova_pval 0 A 1 8.0 33.0 0.004982 0.076120 1 A 2 73.0 34.0 0.004982 0.076120 2 B 1 0.0 86.0 0.002345 0.010234 3 B 2 60.0 70.0 0.002345 0.010234 4 C 1 85.0 65.0 0.345678 0.234567
关键逻辑说明
- 均值计算:通过
groupby(['cat1','cat2']).mean()直接得到子组均值,并重命名列以匹配期望输出格式。 - ANOVA p值计算:嵌套分组——先按
cat1分组,再在每个组内按cat2拆分连续列数据,执行ANOVA后提取p值。每个cat1组的p值会广播到该组下所有cat2子行(因为同一cat1内的ANOVA结果对所有子组一致)。 - 数据合并:通过
merge按cat1关联均值表和p值表,确保每个子组行都带上对应的均值和同组ANOVA p值。
内容的提问来源于stack exchange,提问作者semblable
相关产品推荐
相关产品推荐

