本文目录导读:

我来详细介绍如何使用Pandas进行数据分组效应量计算,包括常见的效应量指标及其Python实现。
准备数据
import pandas as pd
import numpy as np
from scipy import stats
import pingouin as pg
import warnings
warnings.filterwarnings('ignore')
# 创建示例数据
np.random.seed(42)
data = pd.DataFrame({
'group': np.repeat(['A', 'B', 'C'], 50),
'score': np.concatenate([
np.random.normal(70, 10, 50), # 组A
np.random.normal(75, 12, 50), # 组B
np.random.normal(65, 15, 50) # 组C
]),
'category': np.random.choice(['X', 'Y'], 150)
})
print(data.head())
print(f"\n数据集形状: {data.shape}")
分组描述统计
# 分组描述统计
group_stats = data.groupby('group')['score'].agg([
'count', 'mean', 'std', 'min', 'max',
lambda x: x.quantile(0.25),
lambda x: x.quantile(0.75)
]).round(2)
group_stats.columns = ['计数', '均值', '标准差', '最小值', '最大值', '25%分位', '75%分位']
print("各组描述统计:")
print(group_stats)
常见效应量计算
1 Cohen's d (两两比较)
def cohens_d(group1, group2):
"""计算Cohen's d效应量"""
n1, n2 = len(group1), len(group2)
mean1, mean2 = np.mean(group1), np.mean(group2)
var1, var2 = np.var(group1, ddof=1), np.var(group2, ddof=1)
# 合并标准差
pooled_std = np.sqrt(((n1-1)*var1 + (n2-1)*var2) / (n1+n2-2))
d = (mean1 - mean2) / pooled_std
return d
# 计算所有组对之间的Cohen's d
groups = data.groupby('group')['score']
# 使用循环计算
effect_sizes = {}
group_names = list(groups.groups.keys())
for i in range(len(group_names)):
for j in range(i+1, len(group_names)):
g1 = groups.get_group(group_names[i])
g2 = groups.get_group(group_names[j])
d = cohens_d(g1, g2)
effect_sizes[f"{group_names[i]} vs {group_names[j]}"] = round(d, 3)
print("Cohen's d效应量:")
for pair, d in effect_sizes.items():
print(f"{pair}: {d}")
2 Hedges' g (小样本校正)
def hedges_g(group1, group2):
"""计算Hedges' g(Cohen's d的校正版本)"""
n1, n2 = len(group1), len(group2)
d = cohens_d(group1, group2)
# 校正因子
correction = 1 - (3 / (4*(n1+n2) - 9))
g = d * correction
return g
print("\nHedges' g 效应量:")
for i in range(len(group_names)):
for j in range(i+1, len(group_names)):
g1 = groups.get_group(group_names[i])
g2 = groups.get_group(group_names[j])
g = hedges_g(g1, g2)
print(f"{group_names[i]} vs {group_names[j]}: {round(g, 3)}")
3 Eta-squared (η²) 用于方差分析
def eta_squared(data, dv, group_col):
"""计算Eta-squared效应量"""
# 总平方和
grand_mean = data[dv].mean()
ss_total = np.sum((data[dv] - grand_mean)**2)
# 组间平方和
ss_between = 0
for name, group in data.groupby(group_col):
group_mean = group[dv].mean()
ss_between += len(group) * (group_mean - grand_mean)**2
# 组内平方和
ss_within = ss_total - ss_between
# Eta-squared
eta_sq = ss_between / ss_total
return eta_sq
eta_sq = eta_squared(data, 'score', 'group')
print(f"\nEta-squared: {round(eta_sq, 4)}")
print(f"解释:组间差异可解释 {round(eta_sq*100, 2)}% 的方差")
4 Glass's delta
def glass_delta(group1, group2, control_idx=0):
"""计算Glass's delta(使用对照组标准差)"""
mean1, mean2 = np.mean(group1), np.mean(group2)
std_control = np.std([group1, group2][control_idx], ddof=1)
delta = (mean1 - mean2) / std_control
return delta
print("\nGlass's delta (以第一组为对照):")
base_group = groups.get_group(group_names[0])
for i in range(1, len(group_names)):
comp_group = groups.get_group(group_names[i])
delta = glass_delta(comp_group, base_group)
print(f"{group_names[i]} vs {group_names[0]}: {round(delta, 3)}")
使用统计库计算效应量
# 使用pingouin库计算效应量
def calculate_effect_sizes_pingouin(data, dv, between):
"""使用pingouin计算多种效应量"""
from pingouin import pairwise_tests
# 两两比较(自动计算Cohen's d)
pairwise = pairwise_tests(data=data, dv=dv, between=between,
effsize='cohen')
print("Pingouin两两比较结果:")
print(pairwise[['Contrast', 'A', 'B', 'cohen-d']])
return pairwise
try:
results = calculate_effect_sizes_pingouin(data, 'score', 'group')
except:
print("请先安装pingouin: pip install pingouin")
分组效应量可视化
import matplotlib.pyplot as plt
import seaborn as sns
def plot_effect_sizes(data, groups, dv):
"""可视化效应量"""
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 1. 箱线图
ax = axes[0, 0]
sns.boxplot(x=groups, y=dv, data=data, ax=ax)
ax.set_title('分组箱线图')
ax.set_xlabel('组别')
ax.set_ylabel('得分')
# 2. 分布图
ax = axes[0, 1]
for name, group in data.groupby(groups):
sns.kdeplot(data=group[dv], label=name, ax=ax)
ax.set_title('分组分布图')
ax.set_xlabel('得分')
ax.legend()
# 3. 均值和置信区间
ax = axes[1, 0]
group_means = data.groupby(groups)[dv].agg(['mean', 'std', 'count'])
group_means.columns = ['均值', '标准差', '样本量']
# 计算标准误
group_means['标准误'] = group_means['标准差'] / np.sqrt(group_means['样本量'])
x_pos = range(len(group_means))
ax.bar(x_pos, group_means['均值'], yerr=group_means['标准误']*1.96,
capsize=5, alpha=0.7)
ax.set_xticks(x_pos)
ax.set_xticklabels(group_means.index)
ax.set_title('分组均值(95%置信区间)')
ax.set_ylabel('均值')
# 4. 效应量热图
ax = axes[1, 1]
effect_matrix = np.zeros((len(group_names), len(group_names)))
for i in range(len(group_names)):
for j in range(len(group_names)):
if i != j:
g1 = groups.get_group(group_names[i])
g2 = groups.get_group(group_names[j])
effect_matrix[i, j] = cohens_d(g1, g2)
sns.heatmap(effect_matrix, annot=True, fmt='.2f',
xticklabels=group_names, yticklabels=group_names,
cmap='coolwarm', center=0, ax=ax)
ax.set_title('Cohen\'s d 效应量矩阵')
ax.set_xlabel('被比较组')
ax.set_ylabel('参考组')
plt.tight_layout()
plt.show()
# 调用可视化函数
plot_effect_sizes(data, 'group', 'score')
多变量分组效应量
# 多变量分组效应量计算
def multivariate_effect_size(data, dv_cols, group_col):
"""计算多变量分组效应量(基础版)"""
results = {}
for dv in dv_cols:
# 计算各组的均值和标准差
group_stats = data.groupby(group_col)[dv].agg(['mean', 'std'])
# 计算总均值
grand_mean = data[dv].mean()
# 计算Eta-squared
ss_between = 0
ss_total = np.sum((data[dv] - grand_mean)**2)
for name, group in data.groupby(group_col):
group_mean = group[dv].mean()
ss_between += len(group) * (group_mean - grand_mean)**2
eta_sq = ss_between / ss_total
# 计算总体效应量(类似Cohen's f)
cohens_f = np.sqrt(eta_sq / (1 - eta_sq))
results[dv] = {
'eta_squared': round(eta_sq, 4),
'cohens_f': round(cohens_f, 4),
'组均值': group_stats['mean'].to_dict(),
'组标准差': group_stats['std'].to_dict()
}
return pd.DataFrame(results).T
# 多变量分析
dv_cols = ['score'] # 可以添加更多变量
multivariate_results = multivariate_effect_size(data, dv_cols, 'group')
print("\n多变量效应量分析结果:")
print(multivariate_results.round(3))
效应量解释和报告
def interpret_effect_sizes(d_values):
"""解释效应量大小"""
def interpret_single(d):
if abs(d) < 0.2:
return "微小效应"
elif abs(d) < 0.5:
return "小效应"
elif abs(d) < 0.8:
return "中等效应"
else:
return "大效应"
interpretations = {pair: interpret_single(d)
for pair, d in d_values.items()}
return interpretations
# 生成效应量报告
def generate_effect_report(data, group_col, dv):
"""生成完整的效应量分析报告"""
groups = data.groupby(group_col)[dv]
group_names = list(groups.groups.keys())
report = []
report.append("=" * 50)
report.append("效应量分析报告")
report.append("=" * 50)
# 基本信息
report.append(f"\n分析变量: {dv}")
report.append(f"分组变量: {group_col}")
report.append(f"组数: {len(group_names)}")
report.append(f"总样本量: {len(data)}")
# 组间比较
report.append("\n两两组间效应量:")
for i in range(len(group_names)):
for j in range(i+1, len(group_names)):
g1 = groups.get_group(group_names[i])
g2 = groups.get_group(group_names[j])
d = cohens_d(g1, g2)
g = hedges_g(g1, g2)
# 效应量解释
if abs(d) < 0.2:
interpretation = "微小"
elif abs(d) < 0.5:
interpretation = "小"
elif abs(d) < 0.8:
interpretation = "中等"
else:
interpretation = "大"
report.append(f"\n{group_names[i]} vs {group_names[j]}:")
report.append(f" Cohen's d = {d:.3f} ({interpretation}效应)")
report.append(f" Hedges' g = {g:.3f}")
# 总体效应
eta_sq = eta_squared(data, dv, group_col)
report.append(f"\n总体效应量:")
report.append(f" Eta-squared = {eta_sq:.4f}")
report.append(f" 组间解释方差 = {eta_sq*100:.2f}%")
return "\n".join(report)
# 生成报告
report = generate_effect_report(data, 'group', 'score')
print(report)
高级分析:双因素分组效应量
def two_way_effect_sizes(data, dv, factor1, factor2):
"""计算双因素分组效应量"""
results = {}
# 主效应1
results[f'{factor1}主效应'] = {
'eta_squared': eta_squared(data, dv, factor1)
}
# 主效应2
results[f'{factor2}主效应'] = {
'eta_squared': eta_squared(data, dv, factor2)
}
# 交互作用效应(简化版)
data['interaction'] = data[factor1].astype(str) + '_' + data[factor2].astype(str)
# 计算交互效应量
eta_sq_total = eta_squared(data, dv, 'interaction')
eta_sq_f1 = results[f'{factor1}主效应']['eta_squared']
eta_sq_f2 = results[f'{factor2}主效应']['eta_squared']
# 交互效应的eta-squared
results['交互效应'] = {
'eta_squared': eta_sq_total - eta_sq_f1 - eta_sq_f2
}
return pd.DataFrame(results).T
# 执行双因素分析
two_way_results = two_way_effect_sizes(data, 'score', 'group', 'category')
print("\n双因素效应量分析:")
print(two_way_results.round(4))
这些代码提供了完整的Pandas数据分组效应量计算方案,包括:
- 常见效应量指标:Cohen's d、Hedges' g、Eta-squared、Glass's delta
- 自动化和可定制:支持多组比较和自定义效应量函数
- 可视化:提供直观的效应量展示
- 报告生成:自动生成效应量分析报告
- 高级分析:支持双因素和多变量效应量分析
使用时可以根据具体研究需求选择合适的效应量指标并调整参数。