Python案例如何用Pandas做数据分组效应量

wen python案例 1

本文目录导读:

Python案例如何用Pandas做数据分组效应量

  1. 准备数据
  2. 分组描述统计
  3. 常见效应量计算
  4. 使用统计库计算效应量
  5. 分组效应量可视化
  6. 多变量分组效应量
  7. 效应量解释和报告
  8. 高级分析:双因素分组效应量

我来详细介绍如何使用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数据分组效应量计算方案,包括:

  1. 常见效应量指标:Cohen's d、Hedges' g、Eta-squared、Glass's delta
  2. 自动化和可定制:支持多组比较和自定义效应量函数
  3. 可视化:提供直观的效应量展示
  4. 报告生成:自动生成效应量分析报告
  5. 高级分析:支持双因素和多变量效应量分析

使用时可以根据具体研究需求选择合适的效应量指标并调整参数。

抱歉,评论功能暂时关闭!