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

Matplotlib 不同变量范围下Quiver梯度向量不垂直等高线的正确绘制方法

问题本质

梯度在数学定义上始终是所在位置等高线的法向量,出现视觉上不垂直的偏差并非梯度计算错误,核心原因是matplotlib默认会自动适配画布宽高,使x、y轴上单个数据单位对应的屏幕物理长度不相等。
当x、y取值范围不同时,比如x范围[0,5]、y范围[0,10],在常规画布上x方向每单位对应的物理长度仅为y方向的一半。此时直接按数学分量绘制矢量,矢量的视觉斜率会与等高线的视觉切线斜率无法匹配,最终看起来失去垂直关系。

正确实现流程

不需要手动修正矢量分量的比例,仅需两步核心设置即可适配任意x、y取值范围:

  • 第一步:强制坐标轴物理等比例
    调用ax.set_aspect('equal', adjustable='box'),强制x轴和y轴上,1个数据单位对应的画布物理长度完全相等,从根源上消除比例拉伸带来的视觉偏差。

    之前尝试仅用set_xlim、set_ylim调整范围但没有设置aspect,画布自动拉伸的状态下比例依然是错的,自然无法达到垂直效果。

  • 第二步:指定quiver的角度计算逻辑
    调用quiver时显式传入angles='xy'参数,告知绘图工具矢量方向完全按照数据坐标系计算,而非按屏幕坐标系的比例渲染。默认的quiver角度计算会受画布拉伸影响产生变形。

常见误区

  • 手动缩放矢量分量的方案(如给dfdy乘固定scale值)不具备通用性:这种方法只是手动凑当前画布下的比例,一旦后续调整画布尺寸、坐标轴边距,固定的scale值就会再次引入偏差。
  • 单独设置units='xy'无法解决问题:该参数仅控制矢量长度的计量基准,不修正坐标轴本身的物理比例偏差。

可直接复用的完整代码

import numpy as np
import matplotlib.pyplot as plt

def f(x, y):
    return x + 0.1 * x * y

def grad_f(x, y, norm=True):    
    dfdx = 1 + 0.1 * y
    dfdy = 0.1 * x
    if norm:
        norm = np.linalg.norm((dfdx, dfdy), axis=0)
        dfdx /= norm
        dfdy /= norm
    return dfdx, dfdy

# 不等范围的x、y采样
x = np.linspace(0, 5, 10)
y = np.linspace(0, 10, 10)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
dfdx, dfdy = grad_f(X, Y)

fig, ax = plt.subplots(figsize=(8, 8))
ax.set_aspect('equal', adjustable='box')
ax.contour(X, Y, Z, levels=np.arange(1, 20, 2))
ax.quiver(X, Y, dfdx, dfdy, Z, angles='xy')

plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 17:27:05