
本文介绍如何使用 pandas 和 itertools.combinations 高效地对 groupby 得到的多个分组两两配对,执行如 mann-whitney u 检验等统计函数,并支持动态分组数量、灵活输出格式(长表或对称矩阵)。
本文介绍如何使用 pandas 和 itertools.combinations 高效地对 groupby 得到的多个分组两两配对,执行如 mann-whitney u 检验等统计函数,并支持动态分组数量、灵活输出格式(长表或对称矩阵)。
在实际数据分析中,我们常需对按某列(如 'age')分组后的各子样本进行两两非参数检验(例如 Mann-Whitney U 检验),以评估不同类别间数值分布是否存在显著差异。关键挑战在于:分组数量未知且可能较多,需自动枚举所有无序组合(即 C(n,2) 对),避免硬编码或嵌套循环。
最简洁、可扩展的解决方案是结合 pandas.core.groupby.generic.SeriesGroupBy 与 itertools.combinations —— 后者天然支持任意长度可迭代对象的组合生成,无需预先知道分组数。
✅ 推荐方法:组合 GroupBy 对象 + 字典推导式(长表格式)
假设原始 DataFrame df 包含分组列 'age' 和待检验数值列 'value':
from itertools import combinations
from scipy.stats import mannwhitneyu
import pandas as pd
# 构建按 'age' 分组的 SeriesGroupBy(仅提取'value'列)
groups = df.groupby('age')['value']
# 对所有两两分组组合执行 Mann-Whitney U 检验
results = {
(name_a, name_b): mannwhitneyu(series_a, series_b)
for (name_a, series_a), (name_b, series_b) in combinations(groups, 2)
}
# 转为 DataFrame,每行对应一对分组,列包含 statistic 和 pvalue
result_df = pd.DataFrame.from_dict(results, orient='index')
result_df.columns = ['statistic', 'pvalue']
? 说明:
groups是一个SeriesGroupBy对象,其迭代产生(group_name, Series)元组;combinations(groups, 2)自动遍历所有不重复、无序的分组对,完美适配“6个组→15对”的需求,且完全通用——无论分组数是3还是300,代码零修改。
? 进阶输出:生成对称 p 值矩阵(热力图友好)
若需可视化或后续多重检验校正,常需方阵形式(行/列均为唯一分组标签,对角线为0,[i,j] == [j,i]):
from scipy.spatial.distance import squareform
# 获取排序后的唯一分组标签(确保行列顺序一致)
idx = sorted(df['age'].unique())
# 提取所有组合的 p 值,构建上三角向量
p_values = [
mannwhitneyu(a[1], b[1]).pvalue
for a, b in combinations(groups, 2)
]
# 转为对称方阵
p_matrix = pd.DataFrame(
squareform(p_values),
index=idx,
columns=idx
).sort_index().sort_index(axis=1) # 显式排序防索引错位
该矩阵可直接用于 seaborn.heatmap(p_matrix, annot=True, cmap='viridis') 绘制显著性热力图。
⚠️ 注意事项与最佳实践
-
数据完整性:确保每组至少有2个观测值(Mann-Whitney U 要求),建议提前过滤小样本组:
df = df.groupby('age').filter(lambda x: len(x) >= 2).reset_index(drop=True) -
多重检验校正:15+ 次检验会大幅增加假阳性率,强烈建议对
pvalue列应用statsmodels.stats.multitest.multipletests进行 FDR/Bonferroni 校正。 -
性能提示:对超多分组(如 >100 组 → ~5000 对),可考虑使用
concurrent.futures.ProcessPoolExecutor并行化mannwhitneyu调用。 -
函数泛化:将
mannwhitneyu替换为任意双样本函数(如ttest_ind,ks_2samp),只需保证其接受两个 array-like 参数并返回含pvalue属性的对象即可。
此方案兼顾简洁性、可读性与工程鲁棒性,是处理动态分组两两检验任务的标准范式。










