未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用边界与维护说明

本文适用于学习多种均值及其在模拟订单分组、异常值比较和时间序列趋势展示中的计算方法,不构成真实业务增收或投资绩效验证。几何平均收益率示例要求增长因子为正;简单调和平均速度适用于等距离路段,不等距离时按距离加权。股票示例采用252日年化约定,等权组合隐含每日再平衡;均线交易仅统计模拟序列中的完整买卖配对,假定信号当日成交,未计费用、滑点及执行延迟。电商分组均值先行四舍五入后再加权,可能与原始总体均值存在微小舍入差异。股票示例的多列收益率直方图传入单个子图轴,存在重建图形、破坏预设四宫格布局的问题,不宜将该部分视为完整可靠的排版示范。本次仅作结构审阅,未运行代码或进行外部事实及链接核验。

📊 均值(Mean/Average)

abstract 📋 本节概览

  • 🎯 学习目标:深入理解均值的概念、计算方法和在数据分析中的应用
  • 📚 前置知识:数据类型 | 集中趋势指标
  • ⏱️ 预计用时:20分钟
  • 🔧 实践技能:掌握多种均值的计算和Python实现

🌟 均值的本质与定义

note 📖 **什么是均值?**

均值是所有数据值的总和除以数据个数得到的值,它代表了数据的"平衡点"或"重心",是描述数据集中趋势最常用的统计量。

🎯 均值的直观理解

想象你有一个天平,把所有数据点都放在数轴上对应的位置,均值就是让这个天平保持平衡的支点位置。

import numpy as np
import matplotlib.pyplot as plt

# 模拟数据点
data = [2, 4, 6, 8, 10, 12, 14]
mean_value = np.mean(data)

plt.figure(figsize=(12, 6))

# 绘制数据点
plt.scatter(data, [0]*len(data), s=100, alpha=0.7, color='blue', label='数据点')

# 绘制均值线
plt.axvline(x=mean_value, color='red', linestyle='--', linewidth=2, label=f'均值 = {mean_value:.1f}')

# 显示每个点到均值的距离
for i, value in enumerate(data):
    distance = abs(value - mean_value)
    plt.plot([value, mean_value], [0.1, 0.1], 'gray', alpha=0.5)
    plt.text(value, 0.2, f'{value}', ha='center', fontsize=10)
    plt.text((value + mean_value)/2, 0.15, f'{distance:.1f}', ha='center', fontsize=8, color='gray')

plt.ylim(-0.1, 0.4)
plt.xlabel('数值')
plt.title('均值作为数据的平衡点')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

print(f"数据集: {data}")
print(f"均值: {mean_value:.2f}")
print(f"离差平方和: {sum([(x - mean_value)**2 for x in data]):.2f}")
print('这个值是所有可能“中心点”中离差平方和最小的!')

📐 均值的数学定义与公式

🔢 算术平均数(Arithmetic Mean)

总体均值(μ): $$\mu = \frac{1}{N} \sum_{i=1}^{N} x_i = \frac{x_1 + x_2 + ... + x_N}{N}$$

样本均值(x̄): $$\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i = \frac{x_1 + x_2 + ... + x_n}{n}$$

import numpy as np
import pandas as pd

def calculate_mean_manually(data):
    """手动计算均值"""
    return sum(data) / len(data)

def demonstrate_mean_calculation():
 # 示例数据:学生考试成绩
    scores = [85, 92, 78, 96, 88, 91, 84, 89, 93, 87]
    
    print("=== 均值计算演示 ===")
    print(f"原始数据: {scores}")
    print(f"数据个数: {len(scores)}")
    print(f"数据总和: {sum(scores)}")
    print()
    
 # 方法1:手动计算
    manual_mean = calculate_mean_manually(scores)
    print(f"手动计算均值: {manual_mean:.2f}")
    
 # 方法2:NumPy
    numpy_mean = np.mean(scores)
    print(f"NumPy计算均值: {numpy_mean:.2f}")
    
 # 方法3:Pandas
    df = pd.DataFrame({'scores': scores})
    pandas_mean = df['scores'].mean()
    print(f"Pandas计算均值: {pandas_mean:.2f}")
    
 # 方法4:Python内置statistics模块
    import statistics
    builtin_mean = statistics.mean(scores)
    print(f"Statistics模块均值: {builtin_mean:.2f}")
    
    return scores, manual_mean

scores, mean_value = demonstrate_mean_calculation()

🔄 加权平均数(Weighted Mean)

当数据中不同值的重要性不同时,使用加权平均数:

$$\bar{x}_w = \frac{\sum_{i=1}^{n} w_i x_i}{\sum_{i=1}^{n} w_i}$$
import numpy as np
import pandas as pd

def weighted_mean_example():
    """加权平均数实际应用案例"""
    print("=== 学生期末成绩计算(加权平均)===")
    
 # 学生成绩数据
    grades_data = {
        '考试类型': ['平时作业', '期中考试', '期末考试', '课程项目'],
        '成绩': [88, 92, 85, 94],
        '权重': [0.2, 0.3, 0.4, 0.1]  # 权重总和为1
    }
    
    df = pd.DataFrame(grades_data)
    print(df)
    print()
    
 # 计算加权平均
    weighted_avg = np.average(df['成绩'], weights=df['权重'])
    simple_avg = np.mean(df['成绩'])
    
    print(f"简单算术平均: {simple_avg:.2f}")
    print(f"加权平均成绩: {weighted_avg:.2f}")
    print(f"差异: {abs(weighted_avg - simple_avg):.2f}分")
    
 # 详细计算过程
    print("\n详细计算过程:")
    weighted_sum = 0
    weight_sum = 0
    
    for i, row in df.iterrows():
        contribution = row['成绩'] * row['权重']
        weighted_sum += contribution
        weight_sum += row['权重']
        print(f"{row['考试类型']}: {row['成绩']} × {row['权重']} = {contribution:.1f}")
    
    print(f"加权总和: {weighted_sum:.1f}")
    print(f"权重总和: {weight_sum:.1f}")
    print(f"加权平均: {weighted_sum:.1f} ÷ {weight_sum:.1f} = {weighted_avg:.2f}")

weighted_mean_example()

📏 几何平均数(Geometric Mean)

适用于比率、增长率等数据:

$$\bar{x}_g = \sqrt[n]{x_1 \times x_2 \times ... \times x_n} = \left(\prod_{i=1}^{n} x_i\right)^{1/n}$$
import numpy as np
from scipy.stats import gmean
import matplotlib.pyplot as plt

def geometric_mean_example():
    """几何平均数在投资收益率中的应用"""
    print("=== 投资收益率的几何平均(复合年增长率)===")
    
 # 假设5年的投资收益率(百分比形式)
    annual_returns = [8.5, -2.1, 15.3, 6.8, -0.7]  # 年收益率(%)
    
 # 转换为增长倍数(1 + 收益率)
    growth_factors = [1 + r/100 for r in annual_returns]
    
    print(f"年收益率 (%): {annual_returns}")
    print(f"增长倍数: {[f'{x:.3f}' for x in growth_factors]}")
    
 # 计算几何平均数
    geometric_mean_factor = gmean(growth_factors)
    geometric_mean_return = (geometric_mean_factor - 1) * 100
    
 # 对比算术平均数
    arithmetic_mean_return = np.mean(annual_returns)
    
    print(f"\n几何平均收益率: {geometric_mean_return:.2f}%")
    print(f"算术平均收益率: {arithmetic_mean_return:.2f}%")
    print(f"差异: {abs(geometric_mean_return - arithmetic_mean_return):.2f}%")
    
 # 验证复合增长的正确性
    final_value_geometric = (1 + geometric_mean_return/100) ** len(annual_returns)
    final_value_actual = np.prod(growth_factors)
    
    print(f"\n验证:")
    print(f"使用几何平均的最终价值倍数: {final_value_geometric:.4f}")
    print(f"实际复合增长的最终价值倍数: {final_value_actual:.4f}")
    print(f"差异: {abs(final_value_geometric - final_value_actual):.6f}")
    
 # 可视化对比
    plt.figure(figsize=(12, 8))
    
 # 实际增长路径
    years = list(range(len(annual_returns) + 1))
    actual_values = [1.0]  # 初始投资1元
    for factor in growth_factors:
        actual_values.append(actual_values[-1] * factor)
    
 # 几何平均增长路径
    geometric_values = [1.0]
    for i in range(1, len(years)):
        geometric_values.append(geometric_values[0] * (geometric_mean_factor ** i))
    
 # 算术平均增长路径(错误的复合方式)
    arithmetic_factor = 1 + arithmetic_mean_return/100
    arithmetic_values = [1.0]
    for i in range(1, len(years)):
        arithmetic_values.append(arithmetic_values[0] * (arithmetic_factor ** i))
    
    plt.plot(years, actual_values, 'bo-', linewidth=2, label='实际增长路径', markersize=8)
    plt.plot(years, geometric_values, 'r--', linewidth=2, label=f'几何平均({geometric_mean_return:.2f}%/年)')
    plt.plot(years, arithmetic_values, 'g:', linewidth=2, label=f'算术平均({arithmetic_mean_return:.2f}%/年,错误!)')
    
    plt.xlabel('年份')
    plt.ylabel('投资价值倍数')
    plt.title('几何平均 vs 算术平均在复合增长中的差异')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()

geometric_mean_example()

🎵 调和平均数(Harmonic Mean)

适用于比率的平均(如速度、效率等):

$$\bar{x}_h = \frac{n}{\sum_{i=1}^{n} \frac{1}{x_i}} = \frac{n}{\frac{1}{x_1} + \frac{1}{x_2} + ... + \frac{1}{x_n}}$$
from scipy.stats import hmean
import numpy as np

def harmonic_mean_example():
    """调和平均数在速度计算中的应用"""
    print("=== 平均速度计算(调和平均数)===")
    
 # 场景:往返旅行,去程60km/h,回程40km/h,求平均速度
    speed_going = 60  # km/h
    speed_returning = 40  # km/h
    distance = 120  # 单程距离 km
    
    print(f"去程速度: {speed_going} km/h")
    print(f"回程速度: {speed_returning} km/h")
    print(f"单程距离: {distance} km")
    
 # 错误的算术平均计算
    arithmetic_avg_speed = (speed_going + speed_returning) / 2
    
 # 正确的调和平均计算
    harmonic_avg_speed = hmean([speed_going, speed_returning])
    
 # 验证:通过总时间计算实际平均速度
    time_going = distance / speed_going
    time_returning = distance / speed_returning
    total_time = time_going + time_returning
    total_distance = 2 * distance
    actual_avg_speed = total_distance / total_time
    
    print(f"\n去程用时: {time_going:.2f} 小时")
    print(f"回程用时: {time_returning:.2f} 小时")
    print(f"总用时: {total_time:.2f} 小时")
    print(f"总距离: {total_distance} km")
    
    print(f"\n算术平均速度(错误): {arithmetic_avg_speed:.2f} km/h")
    print(f"调和平均速度(正确): {harmonic_avg_speed:.2f} km/h")
    print(f"实际平均速度: {actual_avg_speed:.2f} km/h")
    print(f"调和平均与实际的差异: {abs(harmonic_avg_speed - actual_avg_speed):.6f} km/h")
    
 # 更复杂的例子:多段不同速度的旅程
    print("\n=== 多段旅程的平均速度 ===")
    segments = [
        {'distance': 50, 'speed': 80},  # 高速路段
        {'distance': 30, 'speed': 40},  # 城市路段
        {'distance': 20, 'speed': 60}   # 郊区路段
    ]
    
    total_distance = sum(seg['distance'] for seg in segments)
    total_time = sum(seg['distance'] / seg['speed'] for seg in segments)
    true_avg_speed = total_distance / total_time
    
 # 加权调和平均(以距离为权重)
    distances = [seg['distance'] for seg in segments]
    speeds = [seg['speed'] for seg in segments]
    
    weighted_harmonic_avg = total_distance / sum(d/s for d, s in zip(distances, speeds))
    
    print(f"各路段情况:")
    for i, seg in enumerate(segments, 1):
        time_needed = seg['distance'] / seg['speed']
        print(f"  路段{i}: {seg['distance']}km, {seg['speed']}km/h, 用时{time_needed:.2f}h")
    
    print(f"\n总距离: {total_distance} km")
    print(f"总用时: {total_time:.2f} 小时")
    print(f"实际平均速度: {true_avg_speed:.2f} km/h")
    print(f"加权调和平均速度: {weighted_harmonic_avg:.2f} km/h")
    print(f"差异: {abs(true_avg_speed - weighted_harmonic_avg):.6f} km/h")

harmonic_mean_example()

🎯 均值在实际业务中的应用

📊 电商业务分析

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

def ecommerce_average_analysis():
    """电商业务中的均值分析"""
    np.random.seed(42)
    
 # 模拟电商订单数据
    n_orders = 5000
    
 # 不同用户群体的订单
    vip_orders = np.random.lognormal(mean=5.0, sigma=0.5, size=500)  # VIP用户,高客单价
    regular_orders = np.random.lognormal(mean=4.0, sigma=0.6, size=3000)  # 普通用户
    new_orders = np.random.lognormal(mean=3.5, sigma=0.8, size=1500)  # 新用户,低客单价
    
    all_orders = np.concatenate([vip_orders, regular_orders, new_orders])
    
 # 创建数据框
    user_types = ['VIP'] * 500 + ['Regular'] * 3000 + ['New'] * 1500
    df = pd.DataFrame({
        'order_amount': all_orders,
        'user_type': user_types
    })
    
    print("=== 电商客单价分析 ===")
    
 # 总体统计
    overall_mean = df['order_amount'].mean()
    overall_median = df['order_amount'].median()
    
    print(f"总体客单价均值: ¥{overall_mean:.2f}")
    print(f"总体客单价中位数: ¥{overall_median:.2f}")
    print(f"均值与中位数差异: ¥{abs(overall_mean - overall_median):.2f}")
    
 # 分用户类型分析
    group_stats = df.groupby('user_type')['order_amount'].agg([
        'count', 'mean', 'median', 'std'
    ]).round(2)
    
    print(f"\n各用户群体客单价统计:")
    print(group_stats)
    
 # 加权平均客单价(按订单量加权)
    weighted_mean = np.average(
        group_stats['mean'], 
        weights=group_stats['count']
    )
    print(f"\n加权平均客单价: ¥{weighted_mean:.2f}")
    print(f"与总体均值差异: ¥{abs(weighted_mean - overall_mean):.2f}")
    
 # 可视化分析
    fig, axes = plt.subplots(2, 2, figsize=(15, 12))
    
 # 1. 客单价分布直方图
    axes[0,0].hist(df['order_amount'], bins=50, alpha=0.7, color='skyblue', edgecolor='black')
    axes[0,0].axvline(overall_mean, color='red', linestyle='--', linewidth=2, label=f'均值: ¥{overall_mean:.2f}')
    axes[0,0].axvline(overall_median, color='green', linestyle='--', linewidth=2, label=f'中位数: ¥{overall_median:.2f}')
    axes[0,0].set_title('客单价分布')
    axes[0,0].set_xlabel('客单价 (¥)')
    axes[0,0].set_ylabel('频数')
    axes[0,0].legend()
    
 # 2. 不同用户类型的客单价箱线图
    sns.boxplot(data=df, x='user_type', y='order_amount', ax=axes[0,1])
    axes[0,1].set_title('不同用户类型客单价分布')
    axes[0,1].set_ylabel('客单价 (¥)')
    
 # 3. 用户类型占比饼图
    user_counts = df['user_type'].value_counts()
    axes[1,0].pie(user_counts.values, labels=user_counts.index, autopct='%1.1f%%')
    axes[1,0].set_title('用户类型分布')
    
 # 4. 各用户类型贡献的收入
    revenue_by_type = df.groupby('user_type')['order_amount'].sum()
    axes[1,1].bar(revenue_by_type.index, revenue_by_type.values, color=['gold', 'lightblue', 'lightcoral'])
    axes[1,1].set_title('各用户类型总收入贡献')
    axes[1,1].set_ylabel('总收入 (¥)')
    for i, v in enumerate(revenue_by_type.values):
        axes[1,1].text(i, v + max(revenue_by_type.values)*0.01, f'¥{v:.0f}', ha='center')
    
    plt.tight_layout()
    plt.show()
    
 # 业务洞察
    print(f"\n=== 业务洞察 ===")
    vip_avg = group_stats.loc['VIP', 'mean']
    regular_avg = group_stats.loc['Regular', 'mean']
    new_avg = group_stats.loc['New', 'mean']
    
    print(f"1. VIP用户客单价比普通用户高 {((vip_avg/regular_avg - 1)*100):.1f}%")
    print(f"2. 新用户客单价比普通用户低 {((1 - new_avg/regular_avg)*100):.1f}%")
    
 # 计算如果提升新用户客单价的潜在收益
    new_user_count = len(df[df['user_type'] == 'New'])
    potential_increase = (regular_avg - new_avg) * new_user_count
    print(f"3. 如果新用户客单价提升至普通用户水平,可增收: ¥{potential_increase:.0f}")

ecommerce_average_analysis()

📈 股票投资分析

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

def stock_return_analysis():
    """股票收益率的均值分析"""
    np.random.seed(42)
    
 # 模拟股票价格数据(随机游走)
    days = 252  # 一年交易日
    initial_price = 100
    
 # 模拟三只股票的价格走势
    stocks = {
        'STOCK_A': {'drift': 0.08/252, 'volatility': 0.2/np.sqrt(252)},  # 年化8%收益,20%波动率
        'STOCK_B': {'drift': 0.12/252, 'volatility': 0.3/np.sqrt(252)},  # 年化12%收益,30%波动率
        'STOCK_C': {'drift': 0.05/252, 'volatility': 0.15/np.sqrt(252)}   # 年化5%收益,15%波动率
    }
    
    price_data = {}
    return_data = {}
    
    for stock, params in stocks.items():
 # 生成价格序列
        returns = np.random.normal(params['drift'], params['volatility'], days)
        prices = [initial_price]
        
        for ret in returns:
            prices.append(prices[-1] * (1 + ret))
        
        price_data[stock] = prices[1:]  # 排除初始价格
        return_data[stock] = returns
    
 # 创建日期索引
    dates = pd.date_range(start='2023-01-01', periods=days, freq='B')
    
 # 创建DataFrame
    price_df = pd.DataFrame(price_data, index=dates)
    return_df = pd.DataFrame(return_data, index=dates)
    
    print("=== 股票收益率均值分析 ===")
    
 # 计算各种均值
    stats_summary = pd.DataFrame(index=stocks.keys())
    
    for stock in stocks.keys():
        returns = return_df[stock]
        
 # 各种均值计算
        arithmetic_mean = returns.mean()
        geometric_mean = (1 + returns).prod() ** (1/len(returns)) - 1
        
 # 年化收益率
        annual_arithmetic = arithmetic_mean * 252
        annual_geometric = ((1 + returns).prod()) ** (252/len(returns)) - 1
        
 # 波动率
        volatility = returns.std() * np.sqrt(252)
        
 # 风险调整收益(夏普比率,假设无风险利率3%)
        risk_free_rate = 0.03
        daily_risk_free_rate = (1 + risk_free_rate) ** (1 / 252) - 1
        excess_returns = returns - daily_risk_free_rate
        sharpe_ratio = excess_returns.mean() / excess_returns.std() * np.sqrt(252)
        
        stats_summary.loc[stock, 'Daily_Arithmetic_Mean'] = arithmetic_mean
        stats_summary.loc[stock, 'Daily_Geometric_Mean'] = geometric_mean
        stats_summary.loc[stock, 'Annual_Arithmetic_Return'] = annual_arithmetic
        stats_summary.loc[stock, 'Annual_Geometric_Return'] = annual_geometric
        stats_summary.loc[stock, 'Annual_Volatility'] = volatility
        stats_summary.loc[stock, 'Sharpe_Ratio'] = sharpe_ratio
        stats_summary.loc[stock, 'Final_Price'] = price_df[stock].iloc[-1]
        stats_summary.loc[stock, 'Total_Return'] = (price_df[stock].iloc[-1] / initial_price - 1)
    
    print("股票收益率统计汇总:")
    print(stats_summary.round(4))
    
 # 可视化分析
    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
    
 # 1. 价格走势图
    price_df.plot(ax=axes[0,0], linewidth=2)
    axes[0,0].set_title('股票价格走势')
    axes[0,0].set_ylabel('价格')
    axes[0,0].grid(True, alpha=0.3)
    
 # 2. 日收益率分布
    return_df.hist(bins=30, ax=axes[0,1], alpha=0.7)
    axes[0,1].set_title('日收益率分布')
    axes[0,1].set_xlabel('日收益率')
    
 # 3. 累计收益率
    cumulative_returns = (1 + return_df).cumprod() - 1
    cumulative_returns.plot(ax=axes[1,0], linewidth=2)
    axes[1,0].set_title('累计收益率')
    axes[1,0].set_ylabel('累计收益率')
    axes[1,0].grid(True, alpha=0.3)
    
 # 4. 风险-收益散点图
    axes[1,1].scatter(stats_summary['Annual_Volatility'], stats_summary['Annual_Geometric_Return'], 
                     s=100, alpha=0.7)
    
    for stock in stocks.keys():
        axes[1,1].annotate(stock, 
                          (stats_summary.loc[stock, 'Annual_Volatility'], 
                           stats_summary.loc[stock, 'Annual_Geometric_Return']),
                          xytext=(5, 5), textcoords='offset points')
    
    axes[1,1].set_xlabel('年化波动率')
    axes[1,1].set_ylabel('年化几何收益率')
    axes[1,1].set_title('风险-收益关系')
    axes[1,1].grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    
 # 投资组合分析
    print(f"\n=== 投资组合分析 ===")
    
 # 等权重组合
    portfolio_returns = return_df.mean(axis=1)
    portfolio_annual_return = ((1 + portfolio_returns).prod()) ** (252/len(portfolio_returns)) - 1
    portfolio_volatility = portfolio_returns.std() * np.sqrt(252)
    portfolio_daily_risk_free_rate = (1 + 0.03) ** (1 / 252) - 1
    portfolio_excess_returns = portfolio_returns - portfolio_daily_risk_free_rate
    portfolio_sharpe = portfolio_excess_returns.mean() / portfolio_excess_returns.std() * np.sqrt(252)
    
    print(f"等权重组合年化收益率: {portfolio_annual_return:.2%}")
    print(f"等权重组合年化波动率: {portfolio_volatility:.2%}")
    print(f"等权重组合夏普比率: {portfolio_sharpe:.3f}")
    
 # 与单只股票对比
    print(f"\n单只股票 vs 组合:")
    for stock in stocks.keys():
        individual_sharpe = stats_summary.loc[stock, 'Sharpe_Ratio']
        print(f"{stock} 夏普比率: {individual_sharpe:.3f}")
    
    print(f"组合夏普比率: {portfolio_sharpe:.3f}")
    print(f"分散投资的好处: 组合相比最差单股提升了 {(portfolio_sharpe - stats_summary['Sharpe_Ratio'].min()):.3f}")

stock_return_analysis()

⚠️ 均值的局限性与注意事项

🎭 异常值对均值的影响

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats

def outlier_impact_demo():
    """演示异常值对均值的影响"""
    print("=== 异常值对均值的影响分析 ===")
    
 # 正常数据
    np.random.seed(42)
    normal_data = np.random.normal(50, 10, 100)
    
 # 添加异常值
    data_with_outliers = np.append(normal_data, [150, 200, 250])
    
 # 计算各种统计量
    stats_comparison = pd.DataFrame({
        '统计量': ['均值', '中位数', '众数', '标准差'],
        '正常数据': [
            np.mean(normal_data),
            np.median(normal_data),
            stats.mode(normal_data.round(), keepdims=True)[0][0],
            np.std(normal_data, ddof=1)
        ],
        '含异常值数据': [
            np.mean(data_with_outliers),
            np.median(data_with_outliers),
            stats.mode(data_with_outliers.round(), keepdims=True)[0][0],
            np.std(data_with_outliers, ddof=1)
        ]
    })
    
    stats_comparison['变化幅度'] = (
        (stats_comparison['含异常值数据'] - stats_comparison['正常数据']) / 
        stats_comparison['正常数据'] * 100
    ).round(2)
    
    print(stats_comparison.round(2))
    
 # 可视化对比
    fig, axes = plt.subplots(1, 2, figsize=(15, 6))
    
 # 正常数据分布
    axes[0].hist(normal_data, bins=20, alpha=0.7, color='lightblue', edgecolor='black')
    axes[0].axvline(np.mean(normal_data), color='red', linestyle='--', 
                   label=f'均值: {np.mean(normal_data):.1f}')
    axes[0].axvline(np.median(normal_data), color='green', linestyle='--', 
                   label=f'中位数: {np.median(normal_data):.1f}')
    axes[0].set_title('正常数据分布')
    axes[0].set_xlabel('数值')
    axes[0].set_ylabel('频数')
    axes[0].legend()
    
 # 含异常值数据分布
    axes[1].hist(data_with_outliers, bins=25, alpha=0.7, color='lightcoral', edgecolor='black')
    axes[1].axvline(np.mean(data_with_outliers), color='red', linestyle='--', 
                   label=f'均值: {np.mean(data_with_outliers):.1f}')
    axes[1].axvline(np.median(data_with_outliers), color='green', linestyle='--', 
                   label=f'中位数: {np.median(data_with_outliers):.1f}')
    axes[1].set_title('含异常值数据分布')
    axes[1].set_xlabel('数值')
    axes[1].set_ylabel('频数')
    axes[1].legend()
    
    plt.tight_layout()
    plt.show()
    
    print(f"\n关键观察:")
    print(f"1. 异常值使均值从 {np.mean(normal_data):.1f} 增加到 {np.mean(data_with_outliers):.1f}")
    print(f"2. 中位数相对稳定,仅从 {np.median(normal_data):.1f} 变为 {np.median(data_with_outliers):.1f}")
    print(f"3. 标准差大幅增加 {stats_comparison.iloc[3, 3]:.1f}%,表明数据变异性增大")

outlier_impact_demo()

📊 偏态分布中的均值问题

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import pandas as pd

def skewed_distribution_analysis():
    """偏态分布中均值的问题"""
    print("=== 偏态分布中的均值分析 ===")
    
    np.random.seed(42)
    
 # 生成不同偏态的数据
    normal_data = np.random.normal(50, 15, 1000)
    right_skewed = np.random.exponential(20, 1000) + 30  # 右偏
    left_skewed = 100 - np.random.exponential(20, 1000)  # 左偏
    
    datasets = {
        '正态分布': normal_data,
        '右偏分布': right_skewed,
        '左偏分布': left_skewed
    }
    
 # 计算统计量
    stats_df = pd.DataFrame(index=['均值', '中位数', '众数', '偏度', '峰度'])
    
    for name, data in datasets.items():
        mean_val = np.mean(data)
        median_val = np.median(data)
        mode_val = stats.mode(data.round(), keepdims=True)[0][0]
        skewness = stats.skew(data)
        kurtosis = stats.kurtosis(data)
        
        stats_df[name] = [mean_val, median_val, mode_val, skewness, kurtosis]
    
    print("各分布的统计量对比:")
    print(stats_df.round(3))
    
 # 可视化
    fig, axes = plt.subplots(2, 3, figsize=(18, 12))
    
    colors = ['skyblue', 'lightcoral', 'lightgreen']
    
    for i, (name, data) in enumerate(datasets.items()):
 # 直方图
        axes[0, i].hist(data, bins=30, alpha=0.7, color=colors[i], edgecolor='black', density=True)
        
        mean_val = np.mean(data)
        median_val = np.median(data)
        mode_val = stats.mode(data.round(), keepdims=True)[0][0]
        
        axes[0, i].axvline(mean_val, color='red', linestyle='--', linewidth=2, label=f'均值: {mean_val:.1f}')
        axes[0, i].axvline(median_val, color='green', linestyle='--', linewidth=2, label=f'中位数: {median_val:.1f}')
        axes[0, i].axvline(mode_val, color='blue', linestyle='--', linewidth=2, label=f'众数: {mode_val:.1f}')
        
        axes[0, i].set_title(f'{name}\n偏度: {stats.skew(data):.2f}')
        axes[0, i].set_xlabel('数值')
        axes[0, i].set_ylabel('密度')
        axes[0, i].legend()
        
 # 箱线图
        axes[1, i].boxplot(data, vert=True)
        axes[1, i].set_title(f'{name} 箱线图')
        axes[1, i].set_ylabel('数值')
        
 # 添加统计量标记
        axes[1, i].axhline(mean_val, color='red', linestyle='--', alpha=0.7, label='均值')
        axes[1, i].axhline(median_val, color='green', linestyle='--', alpha=0.7, label='中位数')
    
    plt.tight_layout()
    plt.show()
    
 # 分析均值的代表性
    print(f"\n=== 均值代表性分析 ===")
    for name, data in datasets.items():
        mean_val = np.mean(data)
        median_val = np.median(data)
        
 # 计算有多少数据点小于均值
        below_mean_pct = (data < mean_val).mean() * 100
        below_median_pct = (data < median_val).mean() * 100
        
        print(f"\n{name}:")
        print(f"  小于均值的数据占比: {below_mean_pct:.1f}%")
        print(f"  小于中位数的数据占比: {below_median_pct:.1f}%")
        print(f"  均值与中位数差异: {abs(mean_val - median_val):.2f}")
        
        if abs(stats.skew(data)) > 0.5:
            print(f"  ⚠️  该分布偏度较大,均值可能不是最佳的中心趋势代表")

skewed_distribution_analysis()

🔍 均值的高级应用

📈 移动平均与趋势分析

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def moving_average_analysis():
    """移动平均在时间序列分析中的应用"""
    print("=== 移动平均趋势分析 ===")
    
 # 生成模拟时间序列数据(股价)
    np.random.seed(42)
    dates = pd.date_range('2023-01-01', periods=252, freq='D')
    
 # 基础趋势 + 周期性 + 随机噪声
    trend = np.linspace(100, 120, 252)
    seasonal = 5 * np.sin(2 * np.pi * np.arange(252) / 30)  # 30天周期
    noise = np.random.normal(0, 2, 252)
    
    price = trend + seasonal + noise
    
    df = pd.DataFrame({'price': price}, index=dates)
    
 # 计算不同期间的移动平均
    df['MA_5'] = df['price'].rolling(window=5).mean()    # 5日均线
    df['MA_20'] = df['price'].rolling(window=20).mean()  # 20日均线
    df['MA_60'] = df['price'].rolling(window=60).mean()  # 60日均线
    
 # 指数移动平均
    df['EMA_20'] = df['price'].ewm(span=20).mean()
    
 # 布林带(基于20日移动平均)
    df['BB_upper'] = df['MA_20'] + 2 * df['price'].rolling(window=20).std()
    df['BB_lower'] = df['MA_20'] - 2 * df['price'].rolling(window=20).std()
    
    print(f"数据时间范围: {df.index[0].date()} 到 {df.index[-1].date()}")
    print(f"价格范围: {df['price'].min():.2f} - {df['price'].max():.2f}")
    
 # 可视化
    plt.figure(figsize=(16, 10))
    
 # 主图:价格和移动平均线
    plt.subplot(2, 1, 1)
    plt.plot(df.index, df['price'], label='价格', linewidth=1, alpha=0.7)
    plt.plot(df.index, df['MA_5'], label='5日均线', linewidth=1.5)
    plt.plot(df.index, df['MA_20'], label='20日均线', linewidth=2)
    plt.plot(df.index, df['MA_60'], label='60日均线', linewidth=2)
    plt.plot(df.index, df['EMA_20'], label='20日指数均线', linewidth=1.5, linestyle='--')
    
 # 布林带
    plt.fill_between(df.index, df['BB_upper'], df['BB_lower'], alpha=0.2, color='gray', label='布林带')
    
    plt.title('价格与移动平均线分析')
    plt.ylabel('价格')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
 # 子图:移动平均线的交叉信号
    plt.subplot(2, 1, 2)
    
 # 计算均线交叉信号
    df['signal'] = 0
    df.loc[df['MA_5'] > df['MA_20'], 'signal'] = 1   # 金叉:短期均线上穿长期均线
    df.loc[df['MA_5'] <= df['MA_20'], 'signal'] = -1  # 死叉:短期均线下穿长期均线
    
 # 找出交叉点
    df['signal_change'] = df['signal'].diff()
    golden_cross = df[df['signal_change'] == 2].index  # 死叉转金叉
    death_cross = df[df['signal_change'] == -2].index  # 金叉转死叉
    
    plt.plot(df.index, df['price'], label='价格', color='black', linewidth=1)
    plt.scatter(golden_cross, df.loc[golden_cross, 'price'], 
               color='gold', s=100, marker='^', label=f'金叉信号({len(golden_cross)}次)', zorder=5)
    plt.scatter(death_cross, df.loc[death_cross, 'price'], 
               color='red', s=100, marker='v', label=f'死叉信号({len(death_cross)}次)', zorder=5)
    
    plt.title('移动平均线交叉信号')
    plt.xlabel('日期')
    plt.ylabel('价格')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    plt.tight_layout()
    plt.show()
    
 # 交易信号分析
    print(f"\n=== 交易信号分析 ===")
    print(f"观察期内金叉信号: {len(golden_cross)} 次")
    print(f"观察期内死叉信号: {len(death_cross)} 次")
    
 # 计算信号的盈利性(简化分析)
    if len(golden_cross) > 0 and len(death_cross) > 0:
 # 匹配买入卖出信号
        trades = []
        for i, buy_date in enumerate(golden_cross):
 # 找到下一个卖出信号
            next_sell = death_cross[death_cross > buy_date]
            if len(next_sell) > 0:
                sell_date = next_sell[0]
                buy_price = df.loc[buy_date, 'price']
                sell_price = df.loc[sell_date, 'price']
                return_pct = (sell_price - buy_price) / buy_price * 100
                
                trades.append({
                    'buy_date': buy_date,
                    'sell_date': sell_date,
                    'buy_price': buy_price,
                    'sell_price': sell_price,
                    'return_pct': return_pct,
                    'days_held': (sell_date - buy_date).days
                })
        
        if trades:
            trades_df = pd.DataFrame(trades)
            print(f"\n完整交易次数: {len(trades_df)}")
            print(f"平均收益率: {trades_df['return_pct'].mean():.2f}%")
            print(f"胜率: {(trades_df['return_pct'] > 0).mean()*100:.1f}%")
            print(f"平均持仓天数: {trades_df['days_held'].mean():.1f}天")
            print(f"最大单次收益: {trades_df['return_pct'].max():.2f}%")
            print(f"最大单次亏损: {trades_df['return_pct'].min():.2f}%")

moving_average_analysis()

🔗 学习路径与推荐资源

📚 后续学习建议

  1. 深入理解:
  • 方差分析 - 学习多组总体均值差异的检验方法
  • 标准差 - 方差的平方根,更直观的离散度量
  • 中位数 - 抗异常值的中心趋势指标
  1. 实际应用:
  1. 高级技术:
  • 时间序列 - 动态均值分析
  • 贝叶斯统计 - 后验均值估计

🛠️ 实践建议

# 实践任务清单
practice_tasks = [
    "1. 分析你最近一个月的支出数据,计算日均消费",
    "2. 比较算术平均和几何平均在投资收益计算中的差异", 
    "3. 使用移动平均分析某只股票的价格趋势",
    "4. 计算加权平均分(以学分为权重)",
    "5. 分析异常值对班级平均分的影响",
    "6. 使用调和平均计算往返旅行的平均速度"
]

print("=== 均值学习实践任务 ===")
for task in practice_tasks:
    print(task)

print("\n完成这些任务将帮助你深入理解均值在实际中的应用!")

#统计学 #均值 #平均数 #描述性统计 #集中趋势 #Python #数据分析