共享不同大小子图轴的缩放比例(不共享轴) [英] Share scaling of differntly sized subplots' axes (not sharing axes)

查看:43
本文介绍了共享不同大小子图轴的缩放比例(不共享轴)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 matplotlib,我想用相同的 x 轴比例绘制两个图形,但我想显示不同大小的部分.我该怎么办?

到目前为止,我可以使用 GridSpec 或共享 x 轴的相同大小的子图绘制不同大小的子图.当我同时尝试两者时,较小的子图具有相同的轴但缩放比例较小,而我想要相同的缩放比例和不同的轴,因此共享轴可能是一个错误的想法.

将 numpy 导入为 np导入matplotlib.pyplot作为plt从matplotlib.gridspec导入GridSpecx=np.linspace(0,10,100)y = np.sin(x)x2=np.linspace(0,5,60)y2 = np.cos(x2)fig=plt.figure()gs = GridSpec(2,3)ax1 = fig.add_subplot(gs [0,:])ax1.plot(x,y)ax2 = fig.add_subplot(gs[1,:-1])#using sharex = ax1这里大大减少了ax2的缩放比例ax2.plot(x2,y2)plt.show()

我希望x.axes具有相同的缩放比例,即相同的x值始终彼此精确重叠,

编辑:一种可能的改进是在xlim_changed 事件回调.这样,即使在第一个轴上缩放/平移时,轴仍保持同步.

您注意到, tight_layout()也有一个小问题,但是可以通过直接调用回调函数来轻松解决.

将 numpy 导入为 np导入matplotlib.pyplot作为plt从matplotlib.gridspec导入GridSpecdef on_xlim_changed(事件):# 这里是魔法发生的地方反式= ax2.transAxes + ax1.transData.inverted()((xmin, _), (xmax, _)) = trans.transform([[0, 1], [1, 1]])ax2.set_xlim(xmin,xmax)x = np.linspace(0,25,100)y = np.sin(x)x2 = np.linspace(10, 30, 60)y2 = np.cos(x2)无花果= plt.figure()gs = GridSpec(2,6)ax1 = fig.add_subplot(gs [0,:])ax1.plot(x, y)ax2 = fig.add_subplot(gs [1,3:-1])ax2.plot(x2,y2)#进行演示,表明垂直线最终对齐对于 [ax1, ax2] 中的 ax:对于 [15, 20] 中的位置:ax.axvline(pos)# tiny_layout() 弄乱了坐标轴 xlim#但可以通过调用on_xlim_changed()进行修复fig.tight_layout()on_xlim_changed(无)ax1.callbacks.connect('xlim_changed', on_xlim_changed)plt.show()

With matplotlib, I want to plot two graphs with the same x-axis scale, but I want to show different sized sections. How can I accomplish that?

So far I can plot differently sized subplots with GridSpec or same sized ones who share the x-axis. When I try both at once, the smaller subplot has the same axis but smaller scaled, while I want the same scaling and a different axis, so sharing the axis might be a wrong idea.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

x=np.linspace(0,10,100)
y=np.sin(x)

x2=np.linspace(0,5,60)
y2=np.cos(x2)

fig=plt.figure()

gs=GridSpec(2,3)

ax1 = fig.add_subplot(gs[0, :])
ax1.plot(x,y)

ax2 = fig.add_subplot(gs[1,:-1])
    #using sharex=ax1 here decreases the scaling of ax2 too much
ax2.plot(x2,y2)

plt.show()    

I want the x.axes to have the same scaling, i.e. the same x values are always exactly on top of each other, this should give you an idea. The smaller plot's frame could be expanded or fit the plot, that doesn't matter. As it is now, the scales don't match.

Thanks in advance.

解决方案

This is still a bit rough. I'm sure there's a slightly more elegant way to do this, but you can create a custom transformation (see Transformations Tutorial) between the Axes coordinates of ax2 and the data coordinates of ax1. In other word, your calculating what is the data-value (according to ax1) at the position corresponding to the left and right edges of ax2, and then adjust the xlim of ax2 accordingly.

Here is a demonstration showing that it works even if the second subplot is not aligned in any particular way with the first.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

x=np.linspace(0,25,100)
y=np.sin(x)

x2=np.linspace(10,30,60)
y2=np.cos(x2)

fig=plt.figure()

gs=GridSpec(2,6)

ax1 = fig.add_subplot(gs[0, :])
ax1.plot(x,y)

ax2 = fig.add_subplot(gs[1,3:-1])
ax2.plot(x2,y2)

# here is where the magic happens
trans = ax2.transAxes + ax1.transData.inverted()
((xmin,_),(xmax,_)) = trans.transform([[0,1],[1,1]])
ax2.set_xlim(xmin,xmax)

# for demonstration, show that the vertical lines end up aligned
for ax in [ax1,ax2]:
    for pos in [15,20]:
        ax.axvline(pos)

plt.show()

EDIT: One possible refinement would be to do the transform in the xlim_changed event callback. That way, the axes stay in sync even when zooming/panning in the first axes.

There is also a slight issue with tight_layout() as you noted, but that is easily fixed by calling the callback function directly.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec


def on_xlim_changed(event):
    # here is where the magic happens
    trans = ax2.transAxes + ax1.transData.inverted()
    ((xmin, _), (xmax, _)) = trans.transform([[0, 1], [1, 1]])
    ax2.set_xlim(xmin, xmax)


x = np.linspace(0, 25, 100)
y = np.sin(x)

x2 = np.linspace(10, 30, 60)
y2 = np.cos(x2)

fig = plt.figure()


gs = GridSpec(2, 6)

ax1 = fig.add_subplot(gs[0, :])
ax1.plot(x, y)

ax2 = fig.add_subplot(gs[1, 3:-1])
ax2.plot(x2, y2)

# for demonstration, show that the vertical lines end up aligned
for ax in [ax1, ax2]:
    for pos in [15, 20]:
        ax.axvline(pos)

# tight_layout() messes up the axes xlim
# but can be fixed by calling on_xlim_changed()
fig.tight_layout()
on_xlim_changed(None)

ax1.callbacks.connect('xlim_changed', on_xlim_changed)


plt.show()

这篇关于共享不同大小子图轴的缩放比例(不共享轴)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆