2D箭头图 - matplotlib与MATLAB输出不一致

6 投票
1 回答
4683 浏览
提问于 2025-04-17 23:21

我正在尝试创建一个 matplotlib 脚本,想要生成一个与 MATLAB 脚本产生的箭头图(quiver plot)非常相似的图。

抱歉,我无法上传图片,因为我的权限不够,但基本上我的 Python 脚本生成的图和 MATLAB 的完全不同(箭头方向完全错误)。

我在运行时对比了 MATLAB 和 Python 的数据。X、Y、Z 是一样的,但 梯度 计算得不对,也就是说,Python 中的 U 和 MATLAB 中的 DX 不一样。这是为什么呢??

MATLAB

%2D quiver
[X,Y] = meshgrid(-2:.2:2);
Z = X.*exp(-X.^2 - Y.^2);
[DX,DY] = gradient(Z,.2,.2);
contour(X,Y,Z)
hold on
quiver(X,Y,DX,DY)
%colormap hsv
grid off
hold off

Python

from pylab import *
from numpy import ma
import numpy as np
import matplotlib.pyplot as plt

X,Y = np.meshgrid( np.linspace(-2,2,21),np.linspace(-2,2,21))
Z=X*np.exp(-X*X-Y*Y)

[U,V]=gradient(Z,.2,.2)

print U

figure()
Q = quiver(X,Y,U,V)
show()

1 个回答

6

简单来说,你把 numpy.gradient 当成是用“列”和“行”来索引的。它返回的是 dy, dx,而你期待的是 dx, dy

首先,除非你是在交互式环境中使用,否则 from pylab import * 是个非常糟糕的主意。命名空间会对你有帮助。

考虑到这一点,你现在的例子应该是这样的:

import numpy as np
import matplotlib.pyplot as plt

x, y = np.meshgrid(np.linspace(-2,2,21), np.linspace(-2,2,21))
z = x * np.exp(-x**2 - y**2)

u, v = np.gradient(z, .2, .2)

fig, ax = plt.subplots()
ax.quiver(x, y, u, v)
plt.show()

这样会产生一个箭头指向错误方向的结果:

enter image description here

如果我们把它们调换一下,就能得到正确的结果:

import numpy as np
import matplotlib.pyplot as plt

x, y = np.meshgrid(np.linspace(-2,2,21), np.linspace(-2,2,21))
z = x * np.exp(-x**2 - y**2)

v, u = np.gradient(z, .2, .2)

fig, ax = plt.subplots()
ax.quiver(x, y, u, v)
plt.show()

enter image description here

你也可以考虑使用 numpy.mgrid,因为它更简洁,而且使用起来更一致。numpy.meshgrid 默认会把顺序调换(返回的是 x,y 而不是 y,x),这让它的行为和其他的有些不一致。虽然 np.meshgrid(..., indexing='ij') 可以解决这个问题,但默认的行为还是有点让人困惑。

举个例子:

import numpy as np
import matplotlib.pyplot as plt

y, x = np.mgrid[-2:2:21j, -2:2:21j]
z = x * np.exp(-x**2 - y**2)

v, u = np.gradient(z, .2, .2)

fig, ax = plt.subplots()
ax.quiver(x, y, u, v)
plt.show()

撰写回答