如何在matplotlib中共享轴并仅使用一个均等的纵横比

发布于 2025-02-06 00:30:42 字数 2252 浏览 1 评论 0原文

我想产生一个图形,在左侧显示2D数据,并在右侧显示垂直的所述数据。

我成功地完成了以下MWE的成功:

import matplotlib.pyplot as plt
import numpy as np

nz = 66
nx = 130
ny = 230
h  = 70
ensemble_size = 50

x = np.array([ix*h / 1000 for ix in range(nx)])
y = np.array([iy*h / 1000 for iy in range(ny)])
z = np.array([iz*h / 1000 for iz in range(nz)])

Y, Z = np.meshgrid(y, z, indexing='ij')

vp_min = 1400
vp_max = 3350
p_max = 1200

ix = 42
iy = 81

vp = (vp_max - vp_min)*np.random.rand(nz*nx*ny, ensemble_size) + vp_min
vp_mean = np.mean(vp, axis=1).reshape(nz*nx*ny, 1)

########################################################################

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)

ax1.pcolor(Y, Z, vp_mean.reshape(nz, nx, ny, order='F')[:,ix,:].T, cmap="jet", vmin=vp_min, vmax=vp_max)
ax1.plot(iy*h*np.ones(nz) / 1000, z, "k--")
ax1.set_ylabel(r'Depth ($km$)')
ax1.set_xlabel(r'Y ($km$)')
ax1.set_aspect('equal')

lines = []
for e in range(ensemble_size):
    lines.append( ax2.plot(vp[:,e].reshape(nz, nx, ny, order='F')[:,ix,iy], z, "b", alpha=0.25, label="models") ) 
lines.append( ax2.plot(vp_mean.reshape(nz, nx, ny, order='F')[:,ix,iy], z, "r", alpha=1.0, label="average model") )
plt.setp(lines[1:ensemble_size], label="_")
ax2.set_xlabel(r'$V_p$ ($m/s$)')
ax2.invert_yaxis()
ax2.legend()

########################################################################

plt.savefig("log_" + str(ix) + "_" + str(iy) + ".pdf", bbox_inches='tight')
plt.show(block=False)
plt.close("all")

但是,我对左子图的长宽比 “在此处输入图像说明”

我宁愿拥有以下布局 ”在此处输入图像说明” 但是我不太知道该怎么做。

编辑 但是,我也尝试使用

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True, gridspec_kw={'width_ratios':[5, 1]})
...
ax1.set_aspect(1)

,结果并不是我想要的,因为两个深度轴不再具有相同的尺寸:

I would like to produce a figure where I display a 2d data on the left and a vertical slice of said data on the right.

I successfully did it with the following MWE:

import matplotlib.pyplot as plt
import numpy as np

nz = 66
nx = 130
ny = 230
h  = 70
ensemble_size = 50

x = np.array([ix*h / 1000 for ix in range(nx)])
y = np.array([iy*h / 1000 for iy in range(ny)])
z = np.array([iz*h / 1000 for iz in range(nz)])

Y, Z = np.meshgrid(y, z, indexing='ij')

vp_min = 1400
vp_max = 3350
p_max = 1200

ix = 42
iy = 81

vp = (vp_max - vp_min)*np.random.rand(nz*nx*ny, ensemble_size) + vp_min
vp_mean = np.mean(vp, axis=1).reshape(nz*nx*ny, 1)

########################################################################

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)

ax1.pcolor(Y, Z, vp_mean.reshape(nz, nx, ny, order='F')[:,ix,:].T, cmap="jet", vmin=vp_min, vmax=vp_max)
ax1.plot(iy*h*np.ones(nz) / 1000, z, "k--")
ax1.set_ylabel(r'Depth ($km$)')
ax1.set_xlabel(r'Y ($km$)')
ax1.set_aspect('equal')

lines = []
for e in range(ensemble_size):
    lines.append( ax2.plot(vp[:,e].reshape(nz, nx, ny, order='F')[:,ix,iy], z, "b", alpha=0.25, label="models") ) 
lines.append( ax2.plot(vp_mean.reshape(nz, nx, ny, order='F')[:,ix,iy], z, "r", alpha=1.0, label="average model") )
plt.setp(lines[1:ensemble_size], label="_")
ax2.set_xlabel(r'$V_p$ ($m/s$)')
ax2.invert_yaxis()
ax2.legend()

########################################################################

plt.savefig("log_" + str(ix) + "_" + str(iy) + ".pdf", bbox_inches='tight')
plt.show(block=False)
plt.close("all")

However, I'm unsatisfied by the aspect ratio of my left sub-figure enter image description here.

I would rather have the following layout enter image description here
But I don't quite know how to do it.

EDIT
I also tried to use

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True, gridspec_kw={'width_ratios':[5, 1]})
...
ax1.set_aspect(1)

However, the result isn't quite what I want as the two depth axes do not have the same size anymore:
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌生 2025-02-13 00:30:42

除了手动调整图大小外,第二种方法是使用父母的孩子的intet_axes。您甚至可以在两者之间设置共享,尽管如果您想要的话,您必须删除tick标签:

fig, ax1 = plt.subplots(constrained_layout=True)

ax1.pcolor(Y, Z, vp_mean.reshape(nz, nx, ny, order='F')[:,ix,:].T, cmap="jet", vmin=vp_min, vmax=vp_max)
ax1.plot(iy*h*np.ones(nz) / 1000, z, "k--")
ax1.set_ylabel(r'Depth ($km$)')
ax1.set_xlabel(r'Y ($km$)')
ax1.set_aspect('equal')

ax2 = ax1.inset_axes([1.05, 0, 0.3, 1], transform=ax1.transAxes)
ax1.sharey(ax2)

lines = []
for e in range(ensemble_size):
    lines.append( ax2.plot(vp[:,e].reshape(nz, nx, ny, order='F')[:,ix,iy], z, "b", alpha=0.25, label="models") )
lines.append( ax2.plot(vp_mean.reshape(nz, nx, ny, order='F')[:,ix,iy], z, "r", alpha=1.0, label="average model") )
plt.setp(lines[1:ensemble_size], label="_")
ax2.set_xlabel(r'$V_p$ ($m/s$)')

即使您放大了第一个轴即使是第二个轴也将始终存在。

A second approach, aside from manually adjusting the figure size is to use an inset_axes that is a child of the parent. You can even set up sharing between the two, though you'll have to remove the tick labels if that is what you want:

fig, ax1 = plt.subplots(constrained_layout=True)

ax1.pcolor(Y, Z, vp_mean.reshape(nz, nx, ny, order='F')[:,ix,:].T, cmap="jet", vmin=vp_min, vmax=vp_max)
ax1.plot(iy*h*np.ones(nz) / 1000, z, "k--")
ax1.set_ylabel(r'Depth ($km$)')
ax1.set_xlabel(r'Y ($km$)')
ax1.set_aspect('equal')

ax2 = ax1.inset_axes([1.05, 0, 0.3, 1], transform=ax1.transAxes)
ax1.sharey(ax2)

lines = []
for e in range(ensemble_size):
    lines.append( ax2.plot(vp[:,e].reshape(nz, nx, ny, order='F')[:,ix,iy], z, "b", alpha=0.25, label="models") )
lines.append( ax2.plot(vp_mean.reshape(nz, nx, ny, order='F')[:,ix,iy], z, "r", alpha=1.0, label="average model") )
plt.setp(lines[1:ensemble_size], label="_")
ax2.set_xlabel(r'$V_p$ ($m/s$)')

This has the advantage that the second axes will always be there, even if you zoom the first axes.

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文