如何在Python中实现Statistica风格的去趋势正态概率图?
Python实现Detrended Normal P-Plot(替代Statistica功能)
核心原理
Detrended Normal P-Plot的核心是展示有序数据值与正态分布预期值的偏差,以此判断数据是否符合正态分布:
- X轴为原始数据的有序值
- Y轴为实际值减去正态拟合直线的预期值(即 detrended 偏差)
实现步骤与代码
以下是基于numpy、scipy.stats和matplotlib的完整实现:
1. 导入依赖库
import numpy as np from scipy import stats import matplotlib.pyplot as plt
2. 定义计算与绘图函数
def detrended_normal_p_plot(data): # 对数据排序并计算样本量 sorted_data = np.sort(data) n = len(sorted_data) # 计算每个数据点的经验概率(修正端点偏差,使用(i-0.5)/n) p = (np.arange(n) + 0.5) / n # 计算对应概率的理论正态分位数 theoretical_quantiles = stats.norm.ppf(p) # 拟合有序数据与理论分位数的线性回归(获取正态拟合的趋势线) slope, intercept, _, _, _ = stats.linregress(theoretical_quantiles, sorted_data) # 计算预期值(趋势线上的预测值)和偏差 expected_values = slope * theoretical_quantiles + intercept deviations = sorted_data - expected_values # 绘制Detrended Normal P-Plot plt.figure(figsize=(8, 6)) plt.scatter(sorted_data, deviations, alpha=0.7, label='Data Points') plt.axhline(y=0, color='red', linestyle='--', label='Zero Deviation') # 设置坐标轴与标题 plt.xlabel('Value') plt.ylabel('Deviation from expected value') plt.title('Detrended Normal P-Plot') plt.legend() plt.grid(True, linestyle=':', alpha=0.6) plt.show()
3. 使用示例
将你的一维数据数组传入函数即可生成图表:
# 示例数据(替换为你的实际数据) sample_data = np.random.normal(loc=0, scale=1, size=100) detrended_normal_p_plot(sample_data)
关键细节说明
- 经验概率修正:使用
(i+0.5)/n而非i/n,避免极端值导致的理论分位数计算偏差 - 线性回归拟合:通过拟合理论分位数与有序数据的直线,得到正态分布下的预期值,偏差即为实际值与预期值的差值
- 图表解读:若数据符合正态分布,偏差点会随机分布在Y=0水平线附近;若存在系统性偏离,则说明数据不符合正态分布
内容的提问来源于stack exchange,提问作者Noerigarnhy
相关产品推荐
相关产品推荐

