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

如何用Python绘制附带特征向量的二维置信椭圆

协方差置信椭圆+特征向量叠加可视化实现

直接基于numpy+matplotlib即可实现需求,完整可运行代码如下:

依赖安装

pip install numpy matplotlib scipy

核心实现代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from scipy.stats import chi2

def plot_cov_ellipse(cov, center, conf_scale=2, ax=None, **style_kwargs):
    """
    绘制二维协方差矩阵对应的置信椭圆,同时返回特征值、特征向量用于后续绘制
    :param cov: 2*2协方差矩阵
    :param center: 椭圆中心坐标,即二维数据的均值点
    :param conf_scale: 置信区间缩放系数,由卡方分布分位数计算得到
    :param ax: matplotlib坐标轴对象
    :param style_kwargs: 椭圆样式参数(边框色、填充色、线宽等)
    """
    # 对协方差矩阵的特征值降序排序,保证长轴对应最大特征值
    eig_vals, eig_vecs = np.linalg.eigh(cov)
    sort_idx = eig_vals.argsort()[::-1]
    eig_vals, eig_vecs = eig_vals[sort_idx], eig_vecs[:, sort_idx]

    # 计算椭圆旋转角度(弧度转角度)
    rotate_angle = np.degrees(np.arctan2(*eig_vecs[:, 0][::-1]))
    # 计算椭圆宽高:2倍半轴长度
    ellipse_width, ellipse_height = 2 * conf_scale * np.sqrt(eig_vals)

    if ax is None:
        ax = plt.gca()
    ellipse = Ellipse(
        xy=center, width=ellipse_width, height=ellipse_height,
        angle=rotate_angle, **style_kwargs
    )
    ax.add_patch(ellipse)
    return eig_vals, eig_vecs

# ---------------------- 示例运行 ----------------------
if __name__ == "__main__":
    # 生成模拟二维正态分布数据
    np.random.seed(42)
    data_mean = [2, 3]
    data_cov = [[3, 2], [2, 2]]
    sample_data = np.random.multivariate_normal(data_mean, data_cov, size=1000)
    x, y = sample_data.T

    # 初始化画布
    fig, ax = plt.subplots(figsize=(8, 8))
    # 绘制原始散点
    ax.scatter(x, y, s=12, alpha=0.4, label="样本散点")

    # 从样本计算实际均值和协方差
    calc_mean = np.mean(sample_data, axis=0)
    calc_cov = np.cov(x, y)

    # 计算95%置信度对应的缩放系数(二维数据自由度为2)
    conf_level = 0.95
    chi2_threshold = chi2.ppf(conf_level, df=2)
    conf_scale = np.sqrt(chi2_threshold)

    # 绘制置信椭圆
    eig_vals, eig_vecs = plot_cov_ellipse(
        calc_cov, calc_mean, conf_scale=conf_scale, ax=ax,
        facecolor="none", edgecolor="#c82423", linewidth=2,
        label=f"{int(conf_level*100)}%置信椭圆"
    )

    # 叠加绘制特征向量箭头
    arrow_length_scale = 2
    for idx in range(2):
        vec_dir = eig_vecs[:, idx]
        vec_len = np.sqrt(eig_vals[idx]) * arrow_length_scale
        ax.arrow(
            calc_mean[0], calc_mean[1],
            vec_dir[0] * vec_len, vec_dir[1] * vec_len,
            head_width=0.2, head_length=0.2, fc="#8b0000", ec="#8b0000",
            label=f"特征向量{idx+1}"
        )

    # 调整显示参数
    ax.set_aspect("equal", adjustable="box")
    ax.legend()
    ax.set_xlabel("X轴")
    ax.set_ylabel("Y轴")
    plt.title("协方差置信椭圆与特征向量可视化")
    plt.show()

关键注意事项

  • 置信度不要直接用固定标准差倍数:2倍标准差仅对应二维正态分布约86%的置信区间,要得到指定置信度的椭圆,必须取自由度为2的卡方分布对应分位数的平方根作为缩放系数,常用置信度对应缩放值为:90%≈2.146、95%≈2.448、99%≈3.035。
  • 特征值必须做降序排序,保证椭圆长轴对应最大方差方向,否则会出现角度计算错误。
  • 必须将坐标轴宽高比设为equal,否则椭圆会因坐标轴拉伸出现视觉变形,和实际协方差方向不匹配。
  • 特征向量箭头长度和对应特征值的平方根成正比,和椭圆半轴长度对齐,可通过调整arrow_length_scale参数修改箭头显示长度。

内容的提问来源于stack exchange,提问作者Remz1337

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 22:36:36