简体   繁体   中英

matplotlib subplots with equal aspect ratio and individual colorbars

I would like to draw 4 subplots with an equal aspect ratio and an individual colorbar for each subplot. I am nearly finished, but I the font is very big and the colorbars are badly positioned as they overlap with the x-axes title; see the attached code and resulting image. How to get a better result?

import numpy
import matplotlib.pyplot as plt
data = numpy.random.random((3, 10))
fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=4)
im1 = ax1.pcolormesh(data)
ax1.set_title('IM1')
im2 = ax2.pcolormesh(data)
ax2.set_title('IM2')
im3 = ax3.pcolormesh(data)
ax3.set_title('IM3')
im4 = ax4.pcolormesh(data)
ax4.set_title('IM4')
for ax, tc in zip((ax1, ax2, ax3, ax4), (im1, im2, im3, im4)):
    ax.tick_params(direction='out', which='both', top=True, right=True)
    ax.minorticks_on()
    ax.set_aspect('equal')
    ax.set_xlabel('$x$')
    ax.set_ylabel('$y$')
    fig.colorbar(tc, ax=ax, orientation='horizontal')
fig.tight_layout()
fig.savefig('im.png', dpi=300, bbox_inches='tight')

在此输入图像描述

In addition to my comment:

  1. You can scale the font-size by either changing its size or by changing the size of the figure. If we do the latter you can use: ... plt.subplots(..., figsize=(50,10))

  2. You can better place the colorbar by 'attaching' it to the relevant axis.

For both points see this updated example:

import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

data = numpy.random.random((3, 10))
fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=4,figsize=(50,10))
im1 = ax1.pcolormesh(data)
ax1.set_title('IM1')
im2 = ax2.pcolormesh(data)
ax2.set_title('IM2')
im3 = ax3.pcolormesh(data)
ax3.set_title('IM3')
im4 = ax4.pcolormesh(data)
ax4.set_title('IM4')

for ax, im in zip((ax1, ax2, ax3, ax4), (im1, im2, im3, im4)):
    ax.tick_params(direction='out', which='both', top=True, right=True)
    ax.minorticks_on()
    ax.set_aspect('equal')
    ax.set_xlabel('$x$')
    ax.set_ylabel('$y$')
    div  = make_axes_locatable(ax)
    cax  = div.append_axes("bottom", size="20%", pad=0.5)
    cbar = plt.colorbar(im,cax=cax,orientation='horizontal')

fig.tight_layout()
fig.savefig('im.png', dpi=300, bbox_inches='tight')

Which produces the image below.

在此输入图像描述

I'm only not sure about getting an automatic value to the padding. Maybe somebody else can contribute?

In order to create n subplots with n horizontal colorbars (one below each axes), you can create an axes grid of 2*n axes, where every second axes is much smaller in height. Those smaller axes can host the colorbars.

import numpy as np
import matplotlib.pyplot as plt

n=4
data = np.random.random((3, 10))
ratios = np.ones(2*n)
ratios[1::2]=0.05
fig, axes = plt.subplots(nrows=2*n, figsize=(4,2*n),
                         gridspec_kw={"height_ratios":ratios})

for i,ax in enumerate(axes[::2]):
    im = ax.pcolormesh(data)
    ax.set_title('IM{}'.format(i+1))
    ax.tick_params(direction='out', which='both', top=True, right=True)
    ax.minorticks_on()
    ax.set_aspect('equal')
    ax.set_xlabel('$x$')
    ax.set_ylabel('$y$')
    fig.colorbar(im, cax=axes[2*i+1], orientation='horizontal')

fig.tight_layout()
fig.savefig('im.png', dpi=300, bbox_inches='tight')

plt.show()

在此输入图像描述

You can set font size for each element and change the position of the colorbar. This is my solution:

import numpy
import matplotlib.pyplot as plt
data = numpy.random.random((3, 10))
fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=4)
im1 = ax1.pcolormesh(data)
ax1.set_title('IM1', size = 3) # size arguments for font changes
im2 = ax2.pcolormesh(data)
ax2.set_title('IM2', size = 3)
im3 = ax3.pcolormesh(data)
ax3.set_title('IM3', size = 3)
im4 = ax4.pcolormesh(data)
ax4.set_title('IM4', size = 3)
for ax, tc in zip((ax1, ax2, ax3, ax4), (im1, im2, im3, im4)):
    ax.tick_params(labelsize = 3, direction='out', which='both', top=True, right=True)
    ax.minorticks_on()
    ax.set_aspect('equal')
    ax.set_xlabel('$x$', size = 3)
    ax.set_ylabel('$y$', size = 3)
    cbar = fig.colorbar(tc, ax=ax, orientation='horizontal', pad=0.5) # pad for positioning colorbar
    cbar.ax.tick_params(labelsize=2) # labelsize for colorbar
fig.tight_layout()
fig.savefig('im.png', dpi=300, bbox_inches='tight')

I'm not sure if it's the best way to do this but simple enough to do it quickly :) Also, you should consider the suggestion to set the size of the figure. I hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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