python打卡day56

发布于:2025-06-28 ⋅ 阅读:(22) ⋅ 点赞:(0)
  1. 假设检验基础知识
    1. 原假设与备择假设
    2. P值、统计量、显著水平、置信区间
  2. 白噪声
    1. 白噪声的定义
    2. 自相关性检验:ACF检验和Ljung-Box 检验
    3. 偏自相关性检验:PACF检验
  3. 平稳性
    1. 平稳性的定义
    2. 单位根ADF检验: 越小越平稳
  4. 季节性检验
    1. ACF检验
    2. 序列分解:趋势+季节性+残差

记忆口诀:p越小,落在置信区间外,越拒绝原假设。

作业:自行构造数据集,来检查是否符合这个要求。

import numpy as np
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.seasonal import seasonal_decompose
import pandas as pd
from scipy import stats
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 设置随机种子以便结果可重现
np.random.seed(42)

# 时间设置
num_points = 200
time = np.arange(num_points)

# ==================== 1. 构造不同类型的数据集 ====================

# 1.1 白噪声数据
white_noise = np.random.normal(0, 1, num_points)

# 1.2 非平稳数据(带趋势)
trend_data = 0.05 * time + np.random.normal(0, 1, num_points)

# 1.3 季节性数据
seasonal_data = 3 * np.sin(2 * np.pi * time / 12) + np.random.normal(0, 0.5, num_points)

# 1.4 复合数据(趋势+季节性+噪声)
complex_data = 0.02 * time + 2 * np.sin(2 * np.pi * time / 24) + np.random.normal(0, 0.8, num_points)

# 1.5 随机游走(非平稳)
random_walk = np.cumsum(np.random.normal(0, 1, num_points))

# ==================== 2. 检验函数定义 ====================

def check_white_noise(data, name):
    """检验白噪声属性"""
    print(f"\n=== {name} 白噪声检验 ===")
    
    # 1. 均值检验
    mean_val = np.mean(data)
    print(f"均值: {mean_val:.4f} (接近0为好)")
    
    # 2. 方差稳定性检验
    std_val = np.std(data)
    print(f"标准差: {std_val:.4f}")
    
    # 3. 正态性检验 (Shapiro-Wilk)
    stat, p_value = stats.shapiro(data[:50])  # 取前50个点检验
    print(f"正态性检验 p值: {p_value:.4f} (>0.05为正态分布)")
    
    # 4. 自相关检验 - 绘制ACF图
    fig, ax = plt.subplots(figsize=(10, 4))
    plot_acf(data, lags=30, ax=ax, alpha=0.05)
    ax.set_title(f'{name} - 自相关函数图 (ACF)')
    plt.tight_layout()
    plt.show()
    
    # 5. Ljung-Box检验(检验是否为白噪声)
    from statsmodels.stats.diagnostic import acorr_ljungbox
    lb_stat = acorr_ljungbox(data, lags=10, return_df=True)
    print(f"Ljung-Box检验 p值: {lb_stat['lb_pvalue'].iloc[-1]:.4f} (>0.05为白噪声)")
    
    return mean_val, std_val, p_value

def check_stationarity(data, name):
    """检验平稳性"""
    print(f"\n=== {name} 平稳性检验 ===")
    
    # ADF检验
    adf_result = adfuller(data)
    print(f"ADF统计量: {adf_result[0]:.4f}")
    print(f"p值: {adf_result[1]:.4f} (<0.05拒绝原假设,即序列平稳)")
    print(f"临界值:")
    for key, value in adf_result[4].items():
        print(f"\t{key}: {value:.4f}")
    
    if adf_result[1] < 0.05:
        print("结论: 序列是平稳的")
    else:
        print("结论: 序列是非平稳的")
    
    # 绘制时间序列图
    plt.figure(figsize=(12, 4))
    plt.plot(time, data)
    plt.title(f'{name} - 时间序列图')
    plt.xlabel('时间')
    plt.ylabel('数值')
    plt.grid(True, alpha=0.3)
    plt.show()
    
    return adf_result[1] < 0.05

def check_seasonality(data, name, period=12):
    """检验季节性"""
    print(f"\n=== {name} 季节性检验 ===")
    
    # 创建时间索引
    dates = pd.date_range('2020-01-01', periods=len(data), freq='M')
    ts = pd.Series(data, index=dates)
    
    # 季节性分解
    try:
        decomposition = seasonal_decompose(ts, model='additive', period=period)
        
        # 绘制分解图
        fig, axes = plt.subplots(4, 1, figsize=(12, 10))
        
        decomposition.observed.plot(ax=axes[0], title=f'{name} - 原始序列')
        decomposition.trend.plot(ax=axes[1], title='趋势')
        decomposition.seasonal.plot(ax=axes[2], title='季节性')
        decomposition.resid.plot(ax=axes[3], title='残差')
        
        plt.tight_layout()
        plt.show()
        
        # 计算季节性强度
        seasonal_strength = np.var(decomposition.seasonal.dropna()) / np.var(decomposition.observed.dropna())
        print(f"季节性强度: {seasonal_strength:.4f} (>0.1表示有明显季节性)")
        
        return seasonal_strength > 0.1
        
    except Exception as e:
        print(f"季节性分解失败: {e}")
        return False

def comprehensive_analysis(data, name):
    """综合分析"""
    print(f"\n{'='*50}")
    print(f"正在分析: {name}")
    print(f"{'='*50}")
    
    # 白噪声检验
    mean_val, std_val, normality_p = check_white_noise(data, name)
    
    # 平稳性检验
    is_stationary = check_stationarity(data, name)
    
    # 季节性检验
    has_seasonality = check_seasonality(data, name)
    
    # 综合结论
    print(f"\n=== {name} 综合结论 ===")
    print(f"是否为白噪声: {'是' if abs(mean_val) < 0.1 and normality_p > 0.05 else '否'}")
    print(f"是否平稳: {'是' if is_stationary else '否'}")
    print(f"是否有季节性: {'是' if has_seasonality else '否'}")
    
    return {
        'name': name,
        'is_white_noise': abs(mean_val) < 0.1 and normality_p > 0.05,
        'is_stationary': is_stationary,
        'has_seasonality': has_seasonality
    }

# ==================== 3. 执行分析 ====================

# 分析所有数据集
datasets = {
    '白噪声': white_noise,
    '趋势数据': trend_data,
    '季节性数据': seasonal_data,
    '复合数据': complex_data,
    '随机游走': random_walk
}

results = []
for name, data in datasets.items():
    result = comprehensive_analysis(data, name)
    results.append(result)

# ==================== 4. 结果汇总 ====================

print("\n" + "="*60)
print("所有数据集分析结果汇总")
print("="*60)
print(f"{'数据集':<10} {'白噪声':<8} {'平稳性':<8} {'季节性':<8}")
print("-"*40)
for result in results:
    print(f"{result['name']:<10} {'✓' if result['is_white_noise'] else '✗':<8} {'✓' if result['is_stationary'] else '✗':<8} {'✓' if result['has_seasonality'] else '✗':<8}")

print("\n说明:")
print("✓ = 是/有")
print("✗ = 否/无")
==================================================
正在分析: 白噪声
==================================================

=== 白噪声 白噪声检验 ===
均值: -0.0408 (接近0为好)
标准差: 0.9287
正态性检验 p值: 0.6722 (>0.05为正态分布)

Ljung-Box检验 p值: 0.5465 (>0.05为白噪声)

=== 白噪声 平稳性检验 ===
ADF统计量: -14.7442
p值: 0.0000 (<0.05拒绝原假设,即序列平稳)
临界值:
	1%: -3.4636
	5%: -2.8762
	10%: -2.5746
结论: 序列是平稳的

季节性强度: 0.1341 (>0.1表示有明显季节性)

=== 白噪声 综合结论 ===
是否为白噪声: 是
是否平稳: 是
是否有季节性: 是

==================================================
正在分析: 趋势数据
==================================================

=== 趋势数据 白噪声检验 ===
均值: 5.0609 (接近0为好)
标准差: 3.0424
正态性检验 p值: 0.5101 (>0.05为正态分布)

Ljung-Box检验 p值: 0.0000 (>0.05为白噪声)

=== 趋势数据 平稳性检验 ===
ADF统计量: 0.6586
p值: 0.9890 (<0.05拒绝原假设,即序列平稳)
临界值:
	1%: -3.4660
	5%: -2.8772
	10%: -2.5751
结论: 序列是非平稳的

季节性强度: 0.0110 (>0.1表示有明显季节性)

=== 趋势数据 综合结论 ===
是否为白噪声: 否
是否平稳: 否
是否有季节性: 否

==================================================
正在分析: 季节性数据
==================================================

=== 季节性数据 白噪声检验 ===
均值: 0.0057 (接近0为好)
标准差: 2.1913
正态性检验 p值: 0.0018 (>0.05为正态分布)

Ljung-Box检验 p值: 0.0000 (>0.05为白噪声)

=== 季节性数据 平稳性检验 ===
ADF统计量: -3.0110
p值: 0.0339 (<0.05拒绝原假设,即序列平稳)
临界值:
	1%: -3.4658
	5%: -2.8771
	10%: -2.5751
结论: 序列是平稳的

季节性强度: 0.9562 (>0.1表示有明显季节性)

=== 季节性数据 综合结论 ===
是否为白噪声: 否
是否平稳: 是
是否有季节性: 是

==================================================
正在分析: 复合数据
==================================================

=== 复合数据 白噪声检验 ===
均值: 2.0498 (接近0为好)
标准差: 1.9280
正态性检验 p值: 0.2400 (>0.05为正态分布)

Ljung-Box检验 p值: 0.0000 (>0.05为白噪声)

=== 复合数据 平稳性检验 ===
ADF统计量: -1.0639
p值: 0.7293 (<0.05拒绝原假设,即序列平稳)
临界值:
	1%: -3.4664
	5%: -2.8774
	10%: -2.5752
结论: 序列是非平稳的

季节性强度: 0.0135 (>0.1表示有明显季节性)

=== 复合数据 综合结论 ===
是否为白噪声: 否
是否平稳: 否
是否有季节性: 否

==================================================
正在分析: 随机游走
==================================================

=== 随机游走 白噪声检验 ===
均值: 17.2919 (接近0为好)
标准差: 11.2322
正态性检验 p值: 0.0363 (>0.05为正态分布)

Ljung-Box检验 p值: 0.0000 (>0.05为白噪声)

=== 随机游走 平稳性检验 ===
ADF统计量: -1.2531
p值: 0.6503 (<0.05拒绝原假设,即序列平稳)
临界值:
	1%: -3.4636
	5%: -2.8762
	10%: -2.5746
结论: 序列是非平稳的

季节性强度: 0.0002 (>0.1表示有明显季节性)

=== 随机游走 综合结论 ===
是否为白噪声: 否
是否平稳: 否
是否有季节性: 否

============================================================
所有数据集分析结果汇总
============================================================
数据集        白噪声      平稳性      季节性     
----------------------------------------
白噪声        ✓        ✓        ✓       
趋势数据       ✗        ✗        ✗       
季节性数据      ✗        ✓        ✓       
复合数据       ✗        ✗        ✗       
随机游走       ✗        ✗        ✗       

说明:
✓ = 是/有
✗ = 否/无


网站公告

今日签到

点亮在社区的每一天
去签到