统计分析 #

统计分析概述 #

Pandas 提供了丰富的统计分析功能,可以快速了解数据的分布特征和变量关系。

text
┌─────────────────────────────────────────────────────────────┐
│                    统计分析方法                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  描述统计                                                   │
│  ├── 集中趋势:mean, median, mode                          │
│  ├── 离散程度:std, var, range                             │
│  └── 分布形状:skew, kurt                                  │
│                                                             │
│  相关性分析                                                 │
│  ├── 相关系数:corr                                        │
│  └── 协方差:cov                                           │
│                                                             │
│  分组统计                                                   │
│  ├── groupby                                               │
│  └── pivot_table                                           │
│                                                             │
│  假设检验                                                   │
│  └── scipy.stats                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

准备数据 #

python
import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
    'category': np.random.choice(['A', 'B', 'C'], 100),
    'value1': np.random.normal(100, 15, 100),
    'value2': np.random.normal(50, 10, 100),
    'value3': np.random.normal(0, 1, 100) * 100 + np.random.normal(100, 15, 100)
})

df['value3'] = df['value1'] + np.random.normal(0, 5, 100)  # 与 value1 相关

描述统计 #

基本统计方法 #

python
# 均值
print(df['value1'].mean())

# 中位数
print(df['value1'].median())

# 众数
print(df['category'].mode())

# 标准差
print(df['value1'].std())

# 方差
print(df['value1'].var())

# 最小值
print(df['value1'].min())

# 最大值
print(df['value1'].max())

# 范围
print(df['value1'].max() - df['value1'].min())

# 分位数
print(df['value1'].quantile([0.25, 0.5, 0.75]))

describe 方法 #

python
# 数值列统计
print(df.describe())

# 所有列统计
print(df.describe(include='all'))

# 自定义百分位数
print(df.describe(percentiles=[0.1, 0.5, 0.9]))

# 只统计对象类型
print(df.describe(include=['object']))

# 只统计数值类型
print(df.describe(include=['number']))

集中趋势 #

python
# 均值
print(df.mean(numeric_only=True))

# 中位数
print(df.median(numeric_only=True))

# 众数
print(df.mode())

# 加权平均
weights = np.random.rand(100)
print(np.average(df['value1'], weights=weights))

离散程度 #

python
# 标准差
print(df.std(numeric_only=True))

# 方差
print(df.var(numeric_only=True))

# 极差
print(df.max(numeric_only=True) - df.min(numeric_only=True))

# 四分位距(IQR)
Q1 = df.quantile(0.25, numeric_only=True)
Q3 = df.quantile(0.75, numeric_only=True)
IQR = Q3 - Q1
print(IQR)

# 变异系数
cv = df.std(numeric_only=True) / df.mean(numeric_only=True)
print(cv)

分布形状 #

python
# 偏度
print(df.skew(numeric_only=True))
# 正偏态(>0):右尾较长
# 负偏态(<0):左尾较长

# 峰度
print(df.kurtosis(numeric_only=True))
# 正峰度(>0):比正态分布更尖
# 负峰度(<0):比正态分布更平

累计统计 #

python
# 累计求和
print(df['value1'].cumsum())

# 累计乘积
print(df['value1'].cumprod())

# 累计最大值
print(df['value1'].cummax())

# 累计最小值
print(df['value1'].cummin())

计数统计 #

python
# 非空值计数
print(df.count())

# 唯一值计数
print(df['category'].nunique())

# 值计数
print(df['category'].value_counts())

# 值计数(比例)
print(df['category'].value_counts(normalize=True))

相关性分析 #

相关系数 #

python
# Pearson 相关系数(默认)
print(df[['value1', 'value2', 'value3']].corr())

# Spearman 相关系数
print(df[['value1', 'value2', 'value3']].corr(method='spearman'))

# Kendall 相关系数
print(df[['value1', 'value2', 'value3']].corr(method='kendall'))

# 单列相关性
print(df.corrwith(df['value1'], numeric_only=True))

协方差 #

python
# 协方差矩阵
print(df[['value1', 'value2', 'value3']].cov())

# 单列协方差
print(df['value1'].cov(df['value3']))

相关性可视化 #

python
import matplotlib.pyplot as plt
import seaborn as sns

# 相关性热力图
plt.figure(figsize=(8, 6))
sns.heatmap(df[['value1', 'value2', 'value3']].corr(), 
            annot=True, cmap='coolwarm', center=0)
plt.title('Correlation Heatmap')
plt.show()

# 散点图矩阵
pd.plotting.scatter_matrix(df[['value1', 'value2', 'value3']], 
                            figsize=(10, 8))
plt.show()

分组统计 #

基本分组 #

python
# 单列分组
print(df.groupby('category')['value1'].mean())

# 多列分组
print(df.groupby('category')[['value1', 'value2']].mean())

# 多个聚合函数
print(df.groupby('category')['value1'].agg(['mean', 'std', 'count']))

# 自定义聚合
print(df.groupby('category').agg({
    'value1': ['mean', 'std'],
    'value2': ['min', 'max'],
    'category': 'count'
}))

多级分组 #

python
# 添加分组列
df['group'] = np.random.choice(['X', 'Y'], 100)

# 多级分组
print(df.groupby(['category', 'group'])['value1'].mean())

# 分组后多列聚合
print(df.groupby(['category', 'group']).agg({
    'value1': 'mean',
    'value2': 'std'
}))

分组转换 #

python
# 标准化
df['value1_std'] = df.groupby('category')['value1'].transform(
    lambda x: (x - x.mean()) / x.std()
)

# 填充缺失值
df['value1_filled'] = df.groupby('category')['value1'].transform(
    lambda x: x.fillna(x.mean())
)

# 排名
df['rank'] = df.groupby('category')['value1'].rank()

分组过滤 #

python
# 过滤分组
print(df.groupby('category').filter(lambda x: x['value1'].mean() > 100))

# 过滤后保留原索引
print(df.groupby('category').filter(lambda x: len(x) > 30))

透视表 #

创建透视表 #

python
# 基本透视表
print(pd.pivot_table(df, values='value1', index='category', aggfunc='mean'))

# 多值
print(pd.pivot_table(df, 
                      values=['value1', 'value2'], 
                      index='category', 
                      aggfunc='mean'))

# 多索引
print(pd.pivot_table(df, 
                      values='value1', 
                      index=['category', 'group'], 
                      aggfunc='mean'))

# 多列
print(pd.pivot_table(df, 
                      values='value1', 
                      index='category', 
                      columns='group', 
                      aggfunc='mean'))

# 多聚合函数
print(pd.pivot_table(df, 
                      values='value1', 
                      index='category', 
                      aggfunc=['mean', 'std', 'count']))

交叉表 #

python
# 频数表
print(pd.crosstab(df['category'], df['group']))

# 带边际汇总
print(pd.crosstab(df['category'], df['group'], margins=True))

# 归一化
print(pd.crosstab(df['category'], df['group'], normalize='all'))

# 带值聚合
print(pd.crosstab(df['category'], df['group'], 
                   values=df['value1'], aggfunc='mean'))

假设检验 #

正态性检验 #

python
from scipy import stats

# Shapiro-Wilk 检验
stat, p = stats.shapiro(df['value1'])
print(f'Statistic: {stat}, p-value: {p}')
if p > 0.05:
    print('数据可能服从正态分布')
else:
    print('数据可能不服从正态分布')

# Kolmogorov-Smirnov 检验
stat, p = stats.kstest(df['value1'], 'norm')
print(f'Statistic: {stat}, p-value: {p}')

t 检验 #

python
# 单样本 t 检验
stat, p = stats.ttest_1samp(df['value1'], 100)
print(f't-statistic: {stat}, p-value: {p}')

# 独立样本 t 检验
group_a = df[df['category'] == 'A']['value1']
group_b = df[df['category'] == 'B']['value1']
stat, p = stats.ttest_ind(group_a, group_b)
print(f't-statistic: {stat}, p-value: {p}')

# 配对样本 t 检验
stat, p = stats.ttest_rel(df['value1'], df['value3'])
print(f't-statistic: {stat}, p-value: {p}')

方差分析(ANOVA) #

python
# 单因素方差分析
groups = [df[df['category'] == cat]['value1'] for cat in df['category'].unique()]
stat, p = stats.f_oneway(*groups)
print(f'F-statistic: {stat}, p-value: {p}')

相关性检验 #

python
# Pearson 相关性检验
corr, p = stats.pearsonr(df['value1'], df['value3'])
print(f'Correlation: {corr}, p-value: {p}')

# Spearman 相关性检验
corr, p = stats.spearmanr(df['value1'], df['value3'])
print(f'Correlation: {corr}, p-value: {p}')

卡方检验 #

python
# 卡方独立性检验
contingency_table = pd.crosstab(df['category'], df['group'])
chi2, p, dof, expected = stats.chi2_contingency(contingency_table)
print(f'Chi-square: {chi2}, p-value: {p}')

统计报告 #

python
def statistical_report(df, column):
    print(f"\n{'='*50}")
    print(f"统计报告: {column}")
    print(f"{'='*50}")
    
    data = df[column]
    
    print(f"\n基本统计:")
    print(f"  样本量: {len(data)}")
    print(f"  缺失值: {data.isna().sum()}")
    print(f"  均值: {data.mean():.2f}")
    print(f"  中位数: {data.median():.2f}")
    print(f"  标准差: {data.std():.2f}")
    print(f"  最小值: {data.min():.2f}")
    print(f"  最大值: {data.max():.2f}")
    
    print(f"\n分位数:")
    for q in [0.25, 0.5, 0.75]:
        print(f"  {int(q*100)}%: {data.quantile(q):.2f}")
    
    print(f"\n分布形状:")
    print(f"  偏度: {data.skew():.2f}")
    print(f"  峰度: {data.kurtosis():.2f}")
    
    stat, p = stats.shapiro(data)
    print(f"\n正态性检验 (Shapiro-Wilk):")
    print(f"  统计量: {stat:.4f}")
    print(f"  p-value: {p:.4f}")
    print(f"  结论: {'正态分布' if p > 0.05 else '非正态分布'}")

statistical_report(df, 'value1')

下一步 #

掌握了统计分析后,接下来学习 分组聚合,深入了解 Pandas 强大的分组功能!

最后更新:2026-04-04