You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用probplot绘制多组不同颜色数据的QQ图(Henry直线)

多组数据的彩色QQ图(Henry直线)绘制方案

问题背景

处理服从正态分布的多组数据(子列表对应一组样本),需要绘制QQ图(Henry直线)验证正态性,要求同一张图上用不同颜色区分各组数据,同时保留整体拟合的Henry直线。

现有单颜色合并数据QQ图代码(可运行):

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

Listes = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11,12,13,14,15]]
Liste_cumulee = np.array([])
for i in range(len(Listes)):
     Liste_cumulee   = np.concatenate(( Liste_cumulee,  Listes[i] ), axis = None)

plt.figure()
probplot(Liste_cumulee, dist="norm", plot=plt)
plt.title("Droite de Henry")
plt.xlabel("Quantiles théoriques")
plt.ylabel("Quantiles observés")
plt.grid()
plt.show()

尝试分组绘制时失败,错误代码如下:

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

Listes = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11,12,13,14,15]]
Liste_cumulee = np.array([])
for i in range(len(Listes)):
     Liste_cumulee   = np.concatenate(( Liste_cumulee,  Listes[i] ), axis = None)

# Ajustement de la droite de Henry aux données concaténées
(_, _), (_, intercept, r) = stats.probplot(Liste_cumulee, dist="norm", plot=None)

# Tracé de la droite de Henry
plt.figure()
plt.title(f"Droite de Henry (r={r:.2f})")
plt.xlabel("Quantiles théoriques")
plt.ylabel("Quantiles observés")
plt.grid()

# Tracé des points pour chaque lot de données avec des couleurs différentes
for i, lot in enumerate(Listes):
    plt.plot(np.sort(lot), stats.norm.ppf(np.linspace(0.01, 0.99, len(lot))), marker='o', linestyle='', label=f'Lot {i+1}', color=plt.cm.tab10(i))

# Affichage du graphique
plt.legend()
plt.show()

错误原因

  1. 坐标轴顺序颠倒:QQ图要求x轴是理论分位数,y轴是观测分位数,错误代码中把观测分位数放在x轴、理论分位数放在y轴,导致图像逻辑完全错误。
  2. 理论分位数计算方式不符:stats.probplot默认使用Blom变换计算分位数位置,而非简单的linspace(0.01, 0.99, len(lot)),这会导致分位数点和拟合直线不匹配。

正确实现方案

核心思路:

  • 先通过合并数据计算整体的Henry拟合直线参数
  • 循环处理每组数据,用stats.probplot获取该组的理论分位数和观测分位数,再绘制彩色散点
  • 最后绘制拟合直线,添加图例和标注

完整代码:

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

Listes = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11,12,13,14,15]]
Liste_cumulee = np.concatenate(Listes)  # 简化合并操作

# 1. 计算整体拟合的Henry直线参数
(quantiles_theoriques_tot, quantiles_observes_tot), (slope, intercept, r) = stats.probplot(
    Liste_cumulee, dist="norm", plot=None
)

# 2. 初始化绘图
plt.figure(figsize=(8, 6))
plt.title(f"Droite de Henry (r={r:.2f})")
plt.xlabel("Quantiles théoriques")
plt.ylabel("Quantiles observés")
plt.grid(True, alpha=0.3)

# 3. 循环绘制每组数据的彩色散点
colors = plt.cm.tab10(np.arange(len(Listes)))  # 获取一组区分度高的颜色
for idx, (lot, color) in enumerate(zip(Listes, colors)):
    # 获取当前组的理论分位数和观测分位数
    qq_data = stats.probplot(lot, dist="norm", plot=None)
    q_theo, q_obs = qq_data[0]
    # 绘制散点
    plt.scatter(q_theo, q_obs, marker='o', color=color, label=f'Lot {idx+1}')

# 4. 绘制Henry拟合直线
x_min, x_max = plt.xlim()
y_min = slope * x_min + intercept
y_max = slope * x_max + intercept
plt.plot([x_min, x_max], [y_min, y_max], color='k', linestyle='--', label='Droite de Henry')

# 5. 添加图例并展示
plt.legend()
plt.show()

代码说明

  • 用np.concatenate(Listes)简化数据合并操作
  • 每组数据通过stats.probplot(..., plot=None)获取对应的理论/观测分位数,保证和拟合直线的分位数计算逻辑一致
  • 使用plt.scatter替代plt.plot更适合绘制散点,避免不必要的连线
  • 拟合直线通过计算x轴两端点对应的y值绘制,确保直线贯穿整个图表范围

内容的提问来源于stack exchange,提问作者Hélène BRNT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:32:43