Matplotlib 2个子图,1个颜色条
我花了太长时间研究如何让两个subplots共享相同的y轴,Matplotlib中的两个共享一个颜色条。
发生的事情是,当我在subplot1
或subplot2
调用colorbar()
函数时,它会自动缩放图,使得色条加上图将适合“子图”边界框内,导致两个并排图是两个完全不同的尺寸。
为了解决这个问题,我尝试创build了第三个子图,然后我用黑色的方式渲染了任何情节。 唯一的问题是,现在这两块地块的高度和宽度是不平衡的,我不知道如何使它看起来不错。
这是我的代码:
from __future__ import division import matplotlib.pyplot as plt import numpy as np from matplotlib import patches from matplotlib.ticker import NullFormatter # SIS Functions TE = 1 # Einstein radius g1 = lambda x,y: (TE/2) * (y**2-x**2)/((x**2+y**2)**(3/2)) g2 = lambda x,y: -1*TE*x*y / ((x**2+y**2)**(3/2)) kappa = lambda x,y: TE / (2*np.sqrt(x**2+y**2)) coords = np.linspace(-2,2,400) X,Y = np.meshgrid(coords,coords) g1out = g1(X,Y) g2out = g2(X,Y) kappaout = kappa(X,Y) for i in range(len(coords)): for j in range(len(coords)): if np.sqrt(coords[i]**2+coords[j]**2) <= TE: g1out[i][j]=0 g2out[i][j]=0 fig = plt.figure() fig.subplots_adjust(wspace=0,hspace=0) # subplot number 1 ax1 = fig.add_subplot(1,2,1,aspect='equal',xlim=[-2,2],ylim=[-2,2]) plt.title(r"$\gamma_{1}$",fontsize="18") plt.xlabel(r"x ($\theta_{E}$)",fontsize="15") plt.ylabel(r"y ($\theta_{E}$)",rotation='horizontal',fontsize="15") plt.xticks([-2.0,-1.5,-1.0,-0.5,0,0.5,1.0,1.5]) plt.xticks([-2.0,-1.5,-1.0,-0.5,0,0.5,1.0,1.5]) plt.imshow(g1out,extent=(-2,2,-2,2)) plt.axhline(y=0,linewidth=2,color='k',linestyle="--") plt.axvline(x=0,linewidth=2,color='k',linestyle="--") e1 = patches.Ellipse((0,0),2,2,color='white') ax1.add_patch(e1) # subplot number 2 ax2 = fig.add_subplot(1,2,2,sharey=ax1,xlim=[-2,2],ylim=[-2,2]) plt.title(r"$\gamma_{2}$",fontsize="18") plt.xlabel(r"x ($\theta_{E}$)",fontsize="15") ax2.yaxis.set_major_formatter( NullFormatter() ) plt.axhline(y=0,linewidth=2,color='k',linestyle="--") plt.axvline(x=0,linewidth=2,color='k',linestyle="--") plt.imshow(g2out,extent=(-2,2,-2,2)) e2 = patches.Ellipse((0,0),2,2,color='white') ax2.add_patch(e2) # subplot for colorbar ax3 = fig.add_subplot(1,1,1) ax3.axis('off') cbar = plt.colorbar(ax=ax2) plt.show()
只需将颜色条放置在自己的轴上,并使用subplots_adjust
为其腾出空间。
举一个简单的例子:
import numpy as np import matplotlib.pyplot as plt fig, axes = plt.subplots(nrows=2, ncols=2) for ax in axes.flat: im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1) fig.subplots_adjust(right=0.8) cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7]) fig.colorbar(im, cax=cbar_ax) plt.show()
您可以使用figure.colorbar()
的ax
参数和figure.colorbar()
轴简化Joe Kington的代码。 从文档 :
斧头
无| 父轴对象,新的颜色条轴的空间将被盗取。 如果给出了一个轴列表,将会调整它们的大小,以便为彩条轴腾出空间。
import numpy as np import matplotlib.pyplot as plt fig, axes = plt.subplots(nrows=2, ncols=2) for ax in axes.flat: im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1) fig.colorbar(im, ax=axes.ravel().tolist()) plt.show()
使用make_axes
更容易,并提供更好的结果。 它还提供了自定义色条定位的可能性。 还要注意subplots
共享x和y轴的选项。
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl fig, axes = plt.subplots(nrows=2, ncols=2, sharex=True, sharey=True) for ax in axes.flat: im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1) cax,kw = mpl.colorbar.make_axes([ax for ax in axes.flat]) plt.colorbar(im, cax=cax, **kw) plt.show()
此解决scheme不需要手动调整轴位置或颜色条大小,适用于多行和单行布局,并可与tight_layout()
。 它是从一个画廊的例子 ,使用matplotlib的AxesGrid工具箱中的 ImageGrid
改编。
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import ImageGrid # Set up figure and image grid fig = plt.figure(figsize=(9.75, 3)) grid = ImageGrid(fig, 111, # as in plt.subplot(111) nrows_ncols=(1,3), axes_pad=0.15, share_all=True, cbar_location="right", cbar_mode="single", cbar_size="7%", cbar_pad=0.15, ) # Add data to image grid for ax in grid: im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1) # Colorbar ax.cax.colorbar(im) ax.cax.toggle_label(True) #plt.tight_layout() # Works, but may still require rect paramater to keep colorbar labels visible plt.show()
正如注释中指出的,使用abevieiramota的轴列表的解决scheme效果很好,直到您只使用一行图像。 使用一个合理的长宽比为figsize
帮助,但还远远不够完美。 例如:
import numpy as np import matplotlib.pyplot as plt fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(9.75, 3)) for ax in axes.flat: im = ax.imshow(np.random.random((10,10)), vmin=0, vmax=1) fig.colorbar(im, ax=axes.ravel().tolist()) plt.show()
色条函数提供了缩放参数,这是色条轴大小的缩放因子。 这确实需要一些手动的试验和错误。 例如:
fig.colorbar(im, ax=axes.ravel().tolist(), shrink=0.75)
作为一个偶然发现这个主题的初学者,我想添加一个python-for- dummies改编的abevieiramota非常简洁的答案(因为我处于不得不查看' ravel '的级别来计算他们的代码在做):
import numpy as np import matplotlib.pyplot as plt fig, ((ax1,ax2,ax3),(ax4,ax5,ax6)) = plt.subplots(2,3) axlist = [ax1,ax2,ax3,ax4,ax5,ax6] first = ax1.imshow(np.random.random((10,10)), vmin=0, vmax=1) third = ax3.imshow(np.random.random((12,12)), vmin=0, vmax=1) fig.colorbar(first, ax=axlist) plt.show()
对于像我这样的noobs来说,这样的pythonic要less得多,看看这里发生了什么。
正如在其他答案中指出的那样,这个想法通常是定义一个彩色条所在的坐标轴。 一个尚未提到的将是直接指定在plt.subplots()
创build子图的plt.subplots()
轴。 优点是不需要手动设置轴的位置,在任何情况下,自动方面的颜色条都将与子图完全一样高。 即使在很多使用图像的情况下,结果也会如下所示。
使用plt.subplots()
,使用gridspec_kw
参数可以使色条轴比其他轴小得多。
fig, (ax, ax2, cax) = plt.subplots(ncols=3,figsize=(5.5,3), gridspec_kw={"width_ratios":[1,1, 0.05]})
例:
import matplotlib.pyplot as plt import numpy as np; np.random.seed(1) fig, (ax, ax2, cax) = plt.subplots(ncols=3,figsize=(5.5,3), gridspec_kw={"width_ratios":[1,1, 0.05]}) fig.subplots_adjust(wspace=0.3) im = ax.imshow(np.random.rand(11,8), vmin=0, vmax=1) im2 = ax2.imshow(np.random.rand(11,8), vmin=0, vmax=1) ax.set_ylabel("y label") fig.colorbar(im, cax=cax) plt.show()
如果图的方面是自动缩放的,或者由于图像在宽度方向上的方面(如上所述)而收缩,这可以很好地工作。 但是,如果图像宽而高,结果将如下所示,这可能是不希望的。
将色条高度固定到子图高度的解决scheme是使用mpl_toolkits.axes_grid1.inset_locator.InsetPosition
来设置相对于图像子图轴的色条轴。
import matplotlib.pyplot as plt import numpy as np; np.random.seed(1) from mpl_toolkits.axes_grid1.inset_locator import InsetPosition fig, (ax, ax2, cax) = plt.subplots(ncols=3,figsize=(7,3), gridspec_kw={"width_ratios":[1,1, 0.05]}) fig.subplots_adjust(wspace=0.3) im = ax.imshow(np.random.rand(11,16), vmin=0, vmax=1) im2 = ax2.imshow(np.random.rand(11,16), vmin=0, vmax=1) ax.set_ylabel("y label") ip = InsetPosition(ax2, [1.05,0,0.05,1]) cax.set_axes_locator(ip) fig.colorbar(im, cax=cax, ax=[ax,ax2]) plt.show()