简体   繁体   English

轴('square')和set_xlim之间的python相互作用

[英]python interplay between axis('square') and set_xlim

For a correlation plot I would like to have a plot that is optically square (same length of x and y in pixels) but also has a certain axis limit on x and y.对于相关图,我想要一个光学正方形的图(x 和 y 的长度相同,以像素为单位),但在 x 和 y 上也有一定的轴限制。 I can get each of the 2 separately but not at the same time:我可以分别获得这两个中的每一个,但不能同时获得:

import matplotlib.pyplot as plt

f, (ax1, ax2) = plt.subplots(1, 2)
x = [1 , 4 , 6]
y1 = [4, 7, 9]
y2 = [20, 89, 99]

ax1.plot(x, y1, 'o')
ax2.plot(x, y2, 'o')

myXlim = [0, 8]
ax1.set_xlim(myXlim)
ax2.set_xlim(myXlim)

ax1.axis('square')
ax2.axis('square')
# limit is gone here

ax1.set_xlim(myXlim)
ax2.set_xlim(myXlim)
# square is gone here

plt.show()

If I just use the ax1.set_xlim(myXlim) (and not square ) then I can manually adjust the window size to get what I want but how can I do this automatically?如果我只使用ax1.set_xlim(myXlim) (而不是square ),那么我可以手动调整窗口大小以获得我想要的,但我如何自动执行此操作?

An option to get square subplots is to set the subplot parameters such that the resulting subplots automatically adjust to be square.获得方形子图的一个选项是设置子图参数,以便生成的子图自动调整为方形。 This is a little involved, because all the margins and spacings need to be taken into account.这有点复杂,因为所有的边距和间距都需要考虑在内。

import matplotlib.pyplot as plt

f, (ax1, ax2) = plt.subplots(1, 2)
x = [1 , 4 , 6]
y1 = [4, 7, 9]
y2 = [20, 89, 99]

def square_subplots(fig):
    rows, cols = ax1.get_subplotspec().get_gridspec().get_geometry()
    l = fig.subplotpars.left
    r = fig.subplotpars.right
    t = fig.subplotpars.top
    b = fig.subplotpars.bottom
    wspace = fig.subplotpars.wspace
    hspace = fig.subplotpars.hspace
    figw,figh = fig.get_size_inches()

    axw = figw*(r-l)/(cols+(cols-1)*wspace)
    axh = figh*(t-b)/(rows+(rows-1)*hspace)
    axs = min(axw,axh)
    w = (1-axs/figw*(cols+(cols-1)*wspace))/2.
    h = (1-axs/figh*(rows+(rows-1)*hspace))/2.
    fig.subplots_adjust(bottom=h, top=1-h, left=w, right=1-w)

ax1.plot(x, y1, 'o')
ax2.plot(x, y2, 'o')

#f.tight_layout() # optionally call tight_layout first
square_subplots(f)

plt.show()

The benefit here is to be able to freely zoom and autoscale.这里的好处是能够自由缩放和自动缩放。 The drawback is that once the figure size changes, the subplot sizes are not square any more.缺点是一旦图形大小发生变化,子图大小不再是正方形。 To overcome this drawback, one may in addition register a callback on size changes of the figure.为了克服这个缺点,可以另外注册一个关于图形大小变化的回调。

import matplotlib.pyplot as plt

f, (ax1, ax2) = plt.subplots(1, 2)
x = [1 , 4 , 6]
y1 = [4, 7, 9]
y2 = [20, 89, 99]

class SquareSubplots():
    def __init__(self, fig):
        self.fig = fig
        self.ax = self.fig.axes[0]
        self.figw,self.figh = 0,0
        self.params = [self.fig.subplotpars.left,
                       self.fig.subplotpars.right,
                       self.fig.subplotpars.top,
                       self.fig.subplotpars.bottom,
                       self.fig.subplotpars.wspace,
                       self.fig.subplotpars.hspace]
        self.rows, self.cols = self.ax.get_subplotspec().get_gridspec().get_geometry()
        self.update(None)
        self.cid = self.fig.canvas.mpl_connect('resize_event', self.update)


    def update(self, evt):
        figw,figh = self.fig.get_size_inches()
        if self.figw != figw or self.figh != figh:
            self.figw = figw; self.figh = figh
            l,r,t,b,wspace,hspace = self.params
            axw = figw*(r-l)/(self.cols+(self.cols-1)*wspace)
            axh = figh*(t-b)/(self.rows+(self.rows-1)*hspace)
            axs = min(axw,axh)
            w = (1-axs/figw*(self.cols+(self.cols-1)*wspace))/2.
            h = (1-axs/figh*(self.rows+(self.rows-1)*hspace))/2.
            self.fig.subplots_adjust(bottom=h, top=1-h, left=w, right=1-w)
            self.fig.canvas.draw_idle()

s = SquareSubplots(f)

ax1.plot(x, y1, 'o')
ax2.plot(x, y2, 'o')

plt.show()

The above solution works by restricting the space the subplot has inside of its grid.上述解决方案通过限制子图在其网格内的空间来工作。 An opposite approach, where the size of the subplot is somehow fixed, would be shown in the answer to Create equal aspect (square) plot with multiple axes when data limits are different?当数据限制不同时,在创建具有多个轴的相等方面(正方形)图的答案中将显示一种相反的方法,其中子图的大小以某种方式固定 . .

There is no one word magic like "square", but you can play around with set_aspect after you set the limits (drop the square lines, that affects the axis values): 没有一个像“平方”这样的词魔术,但是您可以在设置限制后放下set_aspect (放下平方线,这会影响轴值):

...
ax1.set_aspect(1.5)
ax2.set_aspect(0.095)
plt.show()

I just played around to get the values above: 我只是玩耍以获得上面的值:

在此处输入图片说明

You can calculate this by dividing the x-range by the y-range - an estimate is 8/5 for ax1 , and 8/85 for ax2 , just by looking at the plots, but you can use the actual values to be precise: 您可以通过将X-范围由Y范围计算这-估计是8/5的ax1和八十五分之八为ax2 ,只要看一眼的故事情节,但可以使用的实际值是精确的:

xr1=ax1.get_xlim()
yr1=ax1.get_ylim()
scale1=(xr1[1]-xr1[0])/(yr1[1]-yr1[0])
ax1.set_aspect(scale1) #1.454545..., almost 1.5!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM