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

Holoviews+Bokeh标准差椭圆方向设置问题求助

解决Holoviews椭圆方向不匹配的问题

你的代码存在几个关键错误,导致椭圆方向无法和散点数据的分布对齐,下面逐一修正并说明:

1. 角度计算逻辑错误

你当前的角度计算代码np.arctan2(eigenvectors[1, order], eigenvectors[1, order])完全无效——这相当于计算arctan2(a,a),结果永远是π/4,根本没用到特征向量的x分量。正确的做法是取对应特征向量的y分量和x分量来计算与水平方向的夹角:

angle = np.arctan2(eigenvectors[1, order], eigenvectors[0, order])

2. 特征向量排序与宽高对应错误

你当前取的是最小特征值对应的特征向量,但椭圆的长轴应该对应最大特征值的方向,同时Holoviews的Ellipse参数是直径,需要用特征值的平方根(即对应轴的标准差)乘以2:

# 按特征值从大到小排序,取最大特征值的索引
order = eigenvalues.argsort()[::-1][0]
# 宽高对应长轴和短轴的直径
w = nstd * np.sqrt(eigenvalues[order]) * 2
h = nstd * np.sqrt(eigenvalues[eigenvalues.argsort()[::-1][1]]) * 2

3. 坐标变换冗余且错误

你手动做的坐标变换不仅冗余,还没对数据做中心化(减去均值),导致标准差计算偏差。实际上直接用特征值计算宽高即可,无需额外变换。

修正后的完整代码

import numpy as np
import holoviews as hv
hv.extension('bokeh')

def create_plot(x, y, nstd=5):
    x, y = np.asarray(x), np.asarray(y)
    cov_matrix = np.cov([x, y])
    eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
    
    # 取最大特征值对应的特征向量(长轴方向)
    order = eigenvalues.argsort()[::-1][0]
    # 计算特征向量与水平方向的逆时针弧度角
    angle = np.arctan2(eigenvectors[1, order], eigenvectors[0, order])
    
    x0 = np.mean(x)
    y0 = np.mean(y)
    
    # 用特征值计算椭圆宽高(Holoviews要求传入直径,故乘以2)
    w = nstd * np.sqrt(eigenvalues[order]) * 2
    h = nstd * np.sqrt(eigenvalues[eigenvalues.argsort()[::-1][1]]) * 2
    
    # 直接传入计算出的角度即可,无需取负
    return hv.Ellipse(x0, y0, (w, h), orientation=angle) * hv.Scatter((x, y))

c2x = np.random.normal(loc=-2, scale=0.6, size=200)
c2y = np.random.normal(loc=-2, scale=0.1, size=200)

combined = create_plot(c2x, c2y)
combined.opts(shared_axes=False, hv.Ellipse(fill_alpha=0.2, color='red'), hv.Scatter(size=5))

核心说明

  • Holoviews的orientation参数定义是宽度对应的轴与水平方向的逆时针弧度角,和特征向量计算出的角度完全匹配,不需要取负。
  • 特征值的平方根就是对应轴方向的标准差,直接用它计算椭圆宽高比手动坐标变换更准确高效。
  • 椭圆的宽高参数是直径,因此需要将标准差乘以2(标准差是中心到边缘的距离,直径为该值的两倍)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:10:37