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

如何将Von Mises KDE适配到Seaborn并绘制极坐标联合密度图

极投影下的二元KDE绘制方案

核心思路:绕开Seaborn限制,手动实现极坐标适配的KDE

Seaborn联合绘图无原生极投影支持,Scipy也没有直接适配极坐标(角度+半径)的二元KDE工具——角度是0-2π的周期变量,半径是非周期正变量,直接用普通二元KDE会出现0/360°边界断层、投影变形问题。下面是针对性的解决方法:

步骤1:处理数据的周期性与格式适配

  • 将角度数据从度转弧度,适配Scipy统计函数的计算逻辑
  • 复制角度边界数据(如把接近2π的数值减2π、接近0的数值加2π),避免KDE在0/2π处出现断裂

步骤2:手动实现极坐标专用二元KDE(推荐方案)

直接用Matplotlib极轴结合Scipy的周期核(Von Mises)+高斯核,绕开Seaborn的限制,代码可直接运行:

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde, vonmises

# 生成模拟数据:角度(弧度)+ 半径
np.random.seed(42)
theta = np.concatenate([vonmises.rvs(kappa=5, size=500), 
                        vonmises.rvs(kappa=5, loc=np.pi, size=500)])
r = np.random.gamma(shape=2, scale=1, size=1000)

# 处理角度周期性:复制边界数据消除断层
theta_extended = np.concatenate([theta, theta - 2*np.pi, theta + 2*np.pi])
r_extended = np.concatenate([r, r, r])

# 自定义极坐标二元KDE:角度用Von Mises核(周期),半径用高斯核
def polar_joint_kde(theta, r, theta_grid, r_grid):
    # 拟合角度的Von Mises分布
    kappa, loc = vonmises.fit(theta)[:2]
    theta_density = vonmises.pdf(theta_grid, kappa=kappa, loc=loc)
    # 拟合半径的高斯KDE
    r_kde = gaussian_kde(r)
    r_density = r_kde(r_grid)
    # 生成联合密度矩阵(假设角度与半径独立,非独立场景需自定义联合核)
    joint_density = np.outer(theta_density, r_density)
    return joint_density

# 创建极坐标网格
theta_grid = np.linspace(0, 2*np.pi, 100)
r_grid = np.linspace(0, r.max(), 50)
T, R = np.meshgrid(theta_grid, r_grid)

# 计算联合密度并绘制等高线
joint_density = polar_joint_kde(theta_extended, r_extended, theta_grid, r_grid)

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(8,8))
contour = ax.contourf(T, R, joint_density, cmap='viridis')
ax.set_theta_zero_location('N')  # 设置0度指向正北
ax.set_theta_direction(-1)  # 角度顺时针递增
plt.colorbar(contour, ax=ax, shrink=0.8)
plt.title('极投影二元KDE等高线图')
plt.show()

步骤3:猴子补丁适配Seaborn联合绘图(可选,稳定性差)

如果一定要用Seaborn的jointplot,可以通过补丁替换其轴创建逻辑,但需注意Seaborn版本更新可能导致失效:

import seaborn as sns
from seaborn.axisgrid import JointGrid

# 替换JointGrid的轴初始化方法,强制主图用极投影
original_init = JointGrid._init_axes
def patched_init(self):
    original_init(self)
    # 替换主图轴为极投影
    self.ax_joint = self.figure.add_subplot(self.gridspec[1,0], projection='polar')
    # 移除默认直角边缘轴,后续需自行适配极坐标边缘图
    self.ax_marg_x.remove()
    self.ax_marg_y.remove()

JointGrid._init_axes = patched_init

# 测试调用(需自行调整边缘图逻辑)
g = sns.jointplot(x=theta, y=r, kind='kde')
g.ax_joint.set_theta_zero_location('N')
plt.show()

关键注意事项

  • 角度的周期性处理是解决0/360°断层的核心,必须复制边界数据
  • 极坐标KDE不能直接用普通二元高斯KDE,角度维度必须用Von Mises周期核
  • Seaborn补丁方案仅适合临时需求,长期使用建议用手动实现的极坐标KDE

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:45:28