在新版matplotlib中使用twinx时定义纵横比

2024-04-23 22:37:53 发布

您现在位置:Python中文网/ 问答频道 /正文

当前版本的matplotlib不再允许box-forced,我应该如何做与answer相同的操作?在

我使用的是matplotlib 3.1.0。在我用twinx()函数在同一绘图上绘制了另一组数据之后,我想将实际绘图区域的纵横比更改为1。在

通常我这样做,它适用于非双轴

ratio = 1
xleft, xright = ax.get_xlim()
ybottom, ytop = ax.get_ylim()
ax.set_aspect(abs((xright - xleft) / (ybottom - ytop)) * ratio)

对于twinx轴,上述代码不起作用,但也不会产生任何错误。
然后我发现了一个answer here

代码基本上使用相同的方法将纵横比设置为1,只是使用了box-forced选项。在

^{pr2}$

我的python中的代码不工作,引发

ValueError: 'box-forced' is not a valid value for adjustable; supported values are 'box', 'datalim'

如果我把它改成'box',它会给出

RuntimeError: Adjustable 'box' is not allowed in a twinned Axes.  Use 'datalim' instead.

我不确定从什么时候开始删除box-forced。 现在我们应该如何以“框”的方式设置纵横比?在

谢谢!在

供参考:matplotlib.axes.Axes.set_adjustable


Tags: 代码answerbox绘图getmatplotlibaxset
2条回答

多亏了@ImportanceOfBeingErnest,但为了在几个子批次中实现这一点,我发现了另一种方法,您的答案激发了我的灵感:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import Divider, Size
from mpl_toolkits.axes_grid1.axes_divider import AxesDivider

def make_patch_spines_invisible(ax):
    ax.set_frame_on(True)
    ax.patch.set_visible(False)
    for sp in ax.spines.values():
        sp.set_visible(False)

def demo_fixed_size_axes():
    fig, axs = plt.subplots(1, 2, figsize=(12, 9))
    axs[0].plot([1, 2, 3])
    axs[1].plot([1, 2, 3.5])
    ax3 = axs[1].twinx()
    ax3.plot([1, 2, 3], [1, 25, 30])

    axs[1].spines['right'].set_visible(False)
    make_patch_spines_invisible(ax4Alt)
    ax4Alt.spines['right'].set_visible(True)

    for ax in fig.get_axes():
        figPos = AxesDivider(ax).get_position()
        h = [Size.Fixed(4)] # has to be fixed
        v = h

        divider = Divider(fig, figPos, h, v, aspect=False)

        ax.set_axes_locator(divider.new_locator(nx=0, ny=0))


if __name__ == "__main__":
    demo_fixed_size_axes()

    plt.show()

缺点是要决定使用哪种尺寸。 我不完全理解我的代码。。。在

正如我just commented在各自的matplotlib问题上

"aspect" in matplotlib always refers to the data, not the axes box. Therefore setting the aspect for twinned or shared axes and letting the box be adjustable actually only makes sense when the scales are the same - or differ by an offset (as opposed to any other linear or nonlinear function). Matplotlib does not perform any check on this, so it disallows for adjustable='box' in such case.

在我看来,在这里使用aspect仅仅是一个解决方法,可以为axes box获得一个固定的比率。Matplotlib目前还没有提供任何清晰的代码路径,但是可以通过调整子绘图参数将轴框强制到正方形空间中

import numpy as np
import matplotlib.pyplot as plt

def squarify(fig):
    w, h = fig.get_size_inches()
    if w > h:
        t = fig.subplotpars.top
        b = fig.subplotpars.bottom
        axs = h*(t-b)
        l = (1.-axs/w)/2
        fig.subplots_adjust(left=l, right=1-l)
    else:
        t = fig.subplotpars.right
        b = fig.subplotpars.left
        axs = w*(t-b)
        l = (1.-axs/h)/2
        fig.subplots_adjust(bottom=l, top=1-l)


x = np.linspace(0,1.6,50) + 50.0

fig, ax = plt.subplots()
ax2 = ax.twinx()

ax.set(xlim = [50.0, 51.6], ylim = [0.0, 1.1])
ax2.set(ylim = [0.0, 11.0])

ax.plot(x,np.sin(x-50.0),'b')
ax2.plot(x,np.cos(x-50.0)*10.,'r')

ax.grid(True, which='major',linestyle='solid')

squarify(fig)
fig.canvas.mpl_connect("resize_event", lambda evt: squarify(fig))

plt.show()

另请参见this answer查看多个子批次。在

如果你想用mpl_toolkits把你的手弄脏,this answer是个不错的读物。在

相关问题 更多 >