33 数据分布情况分析
33.1 引言数据分布的重要性
分布特征:
- 集中趋势: 均值、中位数
- 离散程度: 方差、标准差
- 形状特征: 偏度、峰度
33.2 本章学习目标
先修内容:阅读本章前,建议先完成第 章节 5 章(NumPy 数组创建)、第 章节 6 章(数组运算)与第 章节 10 章(Series 与 DataFrame 基础);涉及可视化时用到第 章节 19 章的绘图基础。
- 用
describe()与 SciPy 计算均值、标准差、分位数、偏度与峰度等分布统计量; - 偏度衡量分布不对称方向、峰度衡量分布尖锐程度的经济含义;
- 超额峰度(Fisher)与 Pearson 峰度两种口径的换算与基准差异;
- 用直方图、箱线图与 Q-Q 图直观判断分布形状与正态性;
- 在教学平台完成随机整数数据集的分布统计任务。
33.3 描述性统计
任务要求:将下方代码原样输入教学平台并运行(注释可省略)。该代码固定随机种子后生成 10000 个 10~19 之间的随机整数,输出 DataFrame 形式的描述性统计表,并计算数据集的偏度与峰度。
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import numpy as np # 导入NumPy数值计算库
import pandas as pd # 导入Pandas数据分析库
from scipy.stats import skew, kurtosis # 导入SciPy科学计算库
# 生成10000个10到20之间的随机整数
np.random.seed(0)
data = np.random.randint(10,20,10000) # 生成随机数
# 描述性统计
data_describe = pd.DataFrame(data).describe()
print("数据集的描述性统计信息:\n", data_describe) # 输出数据集的描述性统计信息:\n
# 计算偏度和峰度
data_skew = skew(data)
data_kurtosis = kurtosis(data) # 计算数据的峰度(衡量分布尖锐程度)
print("数据集的偏度为:", data_skew) # 输出数据集的偏度为
print("数据集的峰度为:", data_kurtosis) # 输出数据集的峰度为预期输出(本书代码环境实跑结果:NumPy 1.26.4、SciPy 1.15.2,随机种子已固定,结果可复现):描述性统计表为 count=10000.000000、mean=14.539700、std=2.885525、min=10.000000、25%=12.000000、50%=15.000000、75%=17.000000、max=19.000000;偏度约为 -0.0096,峰度(超额峰度)约为 -1.2371。判读要点:数据在 10~19 十个整数上近乎等可能取值(离散均匀分布),故均值约居中、偏度接近 0,而均匀分布没有尖峰厚尾,超额峰度为明显负值;若平台环境的库版本不同,数值可能有极微小差异,以平台运行结果为准。
33.4 偏度与峰度
偏度(Skewness): 衡量分布的对称性
\[ \text{Skew} = E\left[\left(\frac{X-\mu}{\sigma}\right)^3\right] \]
- Skew = 0: 对称分布(如正态分布)
- Skew > 0: 右偏(正偏),长尾在右侧
- Skew < 0: 左偏(负偏),长尾在左侧
峰度(Kurtosis): 衡量分布的尖锐程度
\[ \text{Kurt} = E\left[\left(\frac{X-\mu}{\sigma}\right)^4\right] - 3 \]
- Kurt = 0: 正态峰度(以正态分布为基准)
- Kurt > 0: 尖峰分布(更集中)
- Kurt < 0: 平峰分布(更分散)
# ==================== 计算偏度 ====================
# 偏度衡量分布的不对称性,正值表示右偏,负值表示左偏
data_skew = skew(data) # 计算数据的偏度系数
# ==================== 计算峰度 ====================
# 默认fisher=True,计算超额峰度(正态分布为0),与本章公式和平台代码一致
# fisher=False则计算Pearson峰度(正态分布为3)
data_kurtosis = kurtosis(data) # 计算超额峰度
# ==================== 输出偏度和峰度 ====================
print(f'偏度: {data_skew:.4f}') # 打印偏度值,保留4位小数
print(f'峰度: {data_kurtosis:.4f}') # 打印峰度值
# ==================== 偏度解读 ====================
print('\n偏度解读:')
if abs(data_skew) < 0.5: # 偏度绝对值小于0.5
print(' 偏度接近0,分布较为对称') # 近似对称分布
elif data_skew > 0: # 偏度大于0
print(' 正偏,右侧长尾') # 右侧有极端值拉动均值
else: # 偏度小于0
print(' 负偏,左侧长尾') # 左侧有极端值拉动均值
# ==================== 峰度解读 ====================
print('\n峰度解读:')
if abs(data_kurtosis) < 0.5: # 超额峰度接近0
print(' 超额峰度接近0,接近正态分布') # 正态峰度
elif data_kurtosis > 0: # 超额峰度大于0
print(' 尖峰,数据更集中') # 中心集中,尾部较薄
else: # 超额峰度小于0
print(' 平峰,数据更分散') # 中心平坦,尾部较厚峰度的两种口径对照:scipy.stats.kurtosis 默认 fisher=True,计算的是超额峰度(正态分布为0),与本章公式一致,平台代码采用的正是这一默认口径;若设 fisher=False,则计算 Pearson 峰度(正态分布为3),两者恰好相差3。以本节数据(np.random.seed(0) 生成的10000个10~19随机整数,近似均匀分布)为例,超额峰度约为 -1.24,对应 Pearson 峰度约为 1.76。判断”是否接近正态”时,必须与各自口径的基准值(0或3)比较,两种口径不可混用。
33.5 可视化分析
# ==================== 导入绘图库 ====================
import matplotlib.pyplot as plt # 基础绘图库
import seaborn as sns # 统计绘图库
# ==================== 创建画布 ====================
fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # 1行2列的子图,总大小14x6英寸
# ==================== 绘制直方图 ====================
# 直方图展示数据的频率分布,直观显示分布形状
axes[0].hist(data, bins=20, color='steelblue', alpha=0.7, edgecolor='black')
# bins=20: 分成20个区间
# color='steelblue': 钢蓝色填充
# alpha=0.7: 透明度70%
# edgecolor='black': 黑色边框
axes[0].set_title('直方图', fontsize=14) # 设置标题
axes[0].set_xlabel('值', fontsize=12) # x轴标签
axes[0].set_ylabel('频数', fontsize=12) # y轴标签
axes[0].grid(axis='y', alpha=0.3) # 添加y轴网格线
# ==================== 绘制箱线图 ====================
# 箱线图展示数据的五数概括和异常值
axes[1].boxplot(data, vert=True) # vert=True表示垂直方向
axes[1].set_title('箱线图', fontsize=14) # 设置标题
axes[1].set_ylabel('值', fontsize=12) # y轴标签
axes[1].grid(axis='y', alpha=0.3) # 添加y轴网格线
# 箱线图解读:
# 箱子:从Q1(25%)到Q3(75%),包含中间50%的数据
# 中线:中位数(Q2,50%)
# 须:1.5倍IQR(四分位距)范围
# 点:超出须范围的异常值
plt.tight_layout() # 自动调整布局
plt.show() # 显示图形
# ==================== Q-Q图检验正态性 ====================
from scipy import stats # 导入统计模块
plt.figure(figsize=(8, 6)) # 创建8x6英寸的画布
stats.probplot(data, dist='norm', plot=plt) # 绘制Q-Q图
# dist='norm': 与正态分布比较
# plot=plt: 在当前图形上绘制
plt.title('Q-Q图(正态分布检验)', fontsize=14) # 设置标题
plt.grid(True, alpha=0.3) # 添加网格线
plt.tight_layout() # 自动调整布局
plt.show() # 显示图形
# Q-Q图解读:
# 如果数据点大致落在红色参考线上,说明数据符合正态分布
# 如果偏离参考线,说明数据不符合正态分布33.6 金融应用
收益分布分析:
- 正态性检验: 股票收益是否正态分布
- 尾部风险: 极端收益概率
- VaR计算: 基于分布的风险价值
33.7 本章小结
要点:
describe()一行代码给出计数、均值、标准差与五个分位数,是分布分析的第一步;- 偏度刻画不对称方向(右偏长尾在右、左偏长尾在左),峰度刻画尾部厚度与峰值尖锐程度;
scipy.stats.kurtosis默认给超额峰度(正态分布基准为 0),设fisher=False得 Pearson 峰度(基准为 3),两口径恰好相差 3;- 直方图看形状、箱线图看五数概括与离群点、Q-Q 图看正态性,三种图形配合统计量交叉印证。
易错点:
- 拿超额峰度与 3 比较(或拿 Pearson 峰度与 0 比较),口径与基准不匹配导致误判;
- 把”偏度接近 0”直接等同于”正态分布”,忽略了峰度与 Q-Q 图同样需要检验;
- 忽略随机种子的作用,重复运行得到不同样本而误以为计算不稳定;
- 用均值刻画明显偏态数据的集中趋势,而此时中位数往往更稳健。
33.8 动手与思考
以下练习每题附参考答案(默认折叠)。请先独立完成并写下你的判断,再点开对照,最后上机验证。
输出预测:不运行代码,先预测平台任务输出的中位数(50% 分位数)与均值哪个更大、偏度符号是正还是负,再上平台验证你的判断。
参考答案(先写下你的预测再点开)
解题思路:先想分布再想统计量。平台任务固定种子后生成 10000 个 10~19 之间的随机整数,等价于在十个整数上近乎等可能取值的离散均匀分布。对称性判断:均匀分布左右对称,均值与中位数理论上都应在中心 14.5 附近,二者谁大谁小只由抽样波动决定,差异应当极小;偏度判断:对称分布的偏度理论值为 0,样本偏度会在一个很小的邻域内随机偏正或偏负。实测(
np.random.seed(0)固定后可复现):均值 14.5397 略小于中位数 15,偏度约为 -0.0096——轻微左偏但几乎对称,符号落在哪一侧纯属该种子下抽样波动的结果;峰度(超额峰度口径,正态分布为 0)约为 -1.2371,明显为负,因为均匀分布没有尖峰也没有厚尾,比正态分布更“平”。预测时应给出“几乎相等、略偏左”与“偏度接近 0、符号可正可负”的区间式判断,而不是押注单一数值。# 验证脚本:复算平台任务的均值、中位数、偏度与峰度 import numpy as np # 导入NumPy数值计算库 from scipy.stats import skew, kurtosis # 导入SciPy的偏度与峰度函数 np.random.seed(0) # 固定随机种子,与平台任务一致,保证可复现 data = np.random.randint(10, 20, 10000) # 生成10000个10~19之间的随机整数 print('均值:', data.mean()) # 输出样本均值 print('中位数:', np.median(data)) # 输出50%分位数 print('偏度:', skew(data)) # 输出偏度,理论上接近0 print('峰度(超额):', kurtosis(data)) # 输出超额峰度(以正态分布0为基准的口径)预期输出(本机 peter 环境实际运行结果,具体以平台运行结果为准):
均值: 14.5397 中位数: 15.0 偏度: -0.009557712187666845 峰度(超额): -1.2371375367090531回扣本章:对应本章小结“要点”第 1、3 条(
describe()是分布分析第一步;scipy.stats.kurtosis默认给超额峰度)与“易错点”第 3 条(固定随机种子后结果可复现,波动不是计算不稳定)。概念辨析:偏度与峰度分别回答分布的什么问题?一个”左偏但尖峰”的收益分布,两个指标各自说明什么?
参考答案(点开前请先独立完成)
解题思路:偏度回答“分布是否对称、长尾在哪一侧”——它以三阶标准化矩度量不对称性,偏度为 0 近似对称,大于 0 右偏(长尾在右,均值被右侧极端值拉高),小于 0 左偏(长尾在左,均值被左侧极端值拉低,通常均值小于中位数)。峰度回答“分布的峰有多尖、尾有多厚”——以四阶标准化矩(超额口径再减 3)衡量相对正态分布的峰度差异,超额峰度大于 0 为尖峰厚尾(中间更集中、极端值更常见),小于 0 为平峰薄尾。对“左偏但尖峰”的收益分布,两个指标各说一件事:偏度为负说明长尾在左侧,存在幅度更大的极端负收益,均值被向下拉动、低于中位数——日常水平由中位数刻画更稳健;超额峰度为正说明尾部整体比正态分布厚,大小两侧的极端收益出现概率都高于正态假设。两者合起来提示:这是一个“平时稳、偶发大跌”的分布,用正态分布近似会同时低估尾部风险的不对称性与厚度。
回扣本章:对应本章小结“要点”第 2 条(偏度刻画不对称方向,峰度刻画尾部厚度与峰值尖锐程度)与“易错点”第 4 条(明显偏态数据的集中趋势应看中位数)。
概念辨析:本章平台代码的峰度输出约为 -1.24,有人说”负峰度说明数据有厚尾”,这个说法错在哪里?
参考答案(点开前请先独立完成)
解题思路:错在把峰度的符号方向弄反了。峰度(超额口径)以正态分布为 0 基准:正值才是尖峰厚尾——中间更集中、尾部更厚;负值是平峰薄尾——分布更平坦、尾部比正态更薄。本章平台数据是 10~19 十个整数上近乎等可能取值的离散均匀分布,没有尖峰也没有厚尾,故超额峰度约 -1.24,恰好说明它的尾部比正态分布更“薄”、极端值更少,与“厚尾”正好相反。这一判断可再作两重核对:其一,口径核对——-1.24 是超额峰度(正态为 0 的口径),换成 Pearson 峰度约为 1.76,仍明显小于正态的基准 3,两种口径结论一致;其二,图形核对——Q-Q 图上两端分位点会向内弯折,说明极端分位数比正态分布更靠近中心。只有正的超额峰度(如金融日收益率常见的显著正值)才支持“尖峰厚尾”的说法。
回扣本章:对应本章小结“要点”第 3 条(超额峰度与 Pearson 峰度两口径恰好相差 3,基准不可混用)与“易错点”第 1 条(口径与基准不匹配导致误判)。
变式任务:把数据生成语句改为
np.random.normal(15, 3, 10000)(保持np.random.seed(0)),在平台上重跑,观察偏度、峰度与 Q-Q 图如何变化;再改为np.random.randint(10, 20, 100)(样本量缩到 100),偏度的绝对值变大还是变小?这说明了什么?参考答案(点开前请先独立完成)
解题思路:两个变体分别检验“分布形状的影响”与“样本量的影响”。变体一改为正态总体 N(15, 3²):正态分布的理论偏度为 0、超额峰度为 0,样本量 10000 时样本统计量应紧贴理论值——实测偏度 0.0266、超额峰度 -0.0310,都几乎为 0;Q-Q 图由原来的阶梯状弯折变为大体落在参考线上(两端可能仍有轻微离散采样的毛刺),说明数据与正态假设吻合。变体二把样本量缩到 100:偏度绝对值从基准的约 0.0096 增大到约 0.1271,变大了一个量级;这说明样本统计量本身有抽样波动,且波动幅度随样本量减小而放大——小样本下偏度、峰度可能明显偏离总体性质,不能拿小样本算出的形状统计量去断言“分布是否对称、是否正态”,形状检验需要足够大的样本支撑。
# 变式脚本:正态总体与小样本两种变体的偏度峰度对比 import numpy as np # 导入NumPy数值计算库 from scipy.stats import skew, kurtosis # 导入偏度与峰度函数 np.random.seed(0) # 保持原随机种子 data_normal = np.random.normal(15, 3, 10000) # 变体1:改为正态总体N(15,3^2),样本量10000 print('正态总体: 偏度={:.4f}, 超额峰度={:.4f}'.format(skew(data_normal), kurtosis(data_normal))) # 两者都应接近0 np.random.seed(0) # 重新固定种子后再抽取变体2 data_small_sample = np.random.randint(10, 20, 100) # 变体2:随机整数样本量缩到100 print('n=100样本: 偏度={:.4f}, 超额峰度={:.4f}'.format(skew(data_small_sample), kurtosis(data_small_sample))) # 与基准对比 print('n=10000基准: 偏度=-0.0096, 超额峰度=-1.2371') # 平台任务基准值,供对照预期输出(本机 peter 环境实际运行结果,具体以平台运行结果为准):
正态总体: 偏度=0.0266, 超额峰度=-0.0310 n=100样本: 偏度=0.1271, 超额峰度=-1.0706 n=10000基准: 偏度=-0.0096, 超额峰度=-1.2371(注:变式一沿用平台任务的固定种子,在平台与本机均可复现;Q-Q 图变化请在平台或本机运行本章“可视化分析”一节的
stats.probplot代码观察。)回扣本章:对应本章小结“要点”第 4 条(统计量与直方图、Q-Q 图交叉印证)与“易错点”第 3 条——固定种子结果可复现,但换样本(尤其是小样本)统计量会波动,这是抽样规律而非计算不稳定。
思考题:金融收益率常呈”尖峰厚尾”。若风险管理系统假设收益服从正态分布,会系统性低估还是高估极端损失的概率?请结合峰度的含义说明。
参考答案(点开前请先独立完成)
解题思路:结论是会系统性低估极端损失的概率。峰度的含义:正的超额峰度意味着分布“中间更集中、尾部更厚”——大量中等幅度的收益高度集中于均值附近,而大幅偏离(尤其大跌)出现的概率高于正态分布。正态假设只用均值与方差两个参数刻画分布,尾部概率按其钟形曲线指数式衰减;真实的厚尾收益率在远离均值的分位上衰减得慢得多,于是同样标一个“三倍标准差事件”,正态模型给出的概率远小于实际观测频率——尾部越厚(超额峰度越大),低估越严重。判断依据有三:一看偏度与峰度(超额峰度显著为正,且左偏时常更危险);二看 Q-Q 图(尾部分位点系统性地偏离正态参考线,向外弯出);三看分位数直接对比(样本 1% 甚至 0.1% 分位损失的绝对值明显超过正态拟合的分位数)。对风险度量的影响与更稳健的做法:正态假设下的参数化 VaR(如均值减 1.65 倍或 2.33 倍标准差)会低估真实 VaR,资本与保证金计提随之不足;改进方向包括直接使用历史分位数(历史模拟法 VaR)、改用 t 分布等显式厚尾分布、做极端情形的压力测试补充,并定期用回溯检验(实际越界次数是否超出模型预期)校验风险模型对尾部的覆盖能力。
回扣本章:对应本章小结“要点”第 2 条(峰度刻画尾部厚度)与“金融应用”一节(尾部风险与 VaR 计算)——分布形状检验正是风险管理的前置工作。