简体   繁体   中英

multiple colorbars (with different ranges/ticks) for subplots in matplotlib

I am using matplotlib to plot subplots with different colorbars. see code below for more detail.

The goal I want to achieve is the attached colorbars are with different ranges (ticks) for different subplots. This may be accomplished by setting different ci (see code below). For example, the left 2 columns subplots should come with a colorbar with range of 0~100,21 intervals; the right 2 columns subplots should be with a colorbar with range of 0~5, 21 intervals.

However, the first colorbar fails to have 0~100 labels. see attached image. I guess the left subplots are still correct regarding the patterns and colors, with only the 'labels' of the left colorbar wrong.

What should I do to fix this?

Thank you very much!

fig, axs = plt.subplots(nrows=2, ncols=4, figsize=(10, 10)) #, constrained_layout=True)
fig.subplots_adjust(bottom=0.05, top=0.95, left=0.15, right=1.6,
                    wspace=0.1, hspace=0.15)

for i, ax in enumerate(axs.flat):
    cmap = plt.get_cmap('gist_earth_r')
    cmap.set_over('navy')
    cmap.set_under('white')
    if i < 2 or (i >= 4 and i<= 5):
        ci = np.linspace(0., 100., 21)
    else:
        ci = np.linspace(0.,5.,21)

    norm = matplotlib.colors.BoundaryNorm(ci, cmap.N)
    pcm = ax.pcolormesh( x, z, cs[i], cmap=cmap, norm=norm )
    ax.set_xticks([-90,-60,-30,0,30,60,90])
    ax.set_xticklabels(['90S','60S','30S','0','30N','60N','90N'])
    ax.set_yticks([1000,850,700,500,300,100])
    ax.set_ylabel('')
    ax.set_xlabel('')
    ax.invert_yaxis()
    ax.set_title(titles[i],loc='center',pad='5')#,fontdict=font)
    ax.xaxis.set_major_formatter(ticker.NullFormatter())
    ax.yaxis.set_major_formatter(ticker.NullFormatter())


fig.colorbar(pcm, ax=axs[:, :2], shrink=0.6, location='bottom',extend='both', pad=0.05)
fig.colorbar(pcm, ax=axs[:, 2:], location='bottom', shrink=0.6, extend='both', pad=0.05)
#fig.colorbar(pcm, ax=[axs[1, 1]], location='right')


plt.show()


  [1]: https://i.stack.imgur.com/VDHdw.jpg

I have rewritten a bit. The main problem is that you are calling colorbar twice on the same pcolormesh, because you do it outside of the loop. Also, it seems to me that the changes you want to apply on the colorbar only require vmin and vmax to be provided to pcolormesh (rather than a norm) and ticks to be given in the call to colorbar. Example snippet and figure below:

import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(nrows=2, ncols=4, sharex=True, sharey=True,
                        figsize=(20, 16))
fig.subplots_adjust(bottom=0.05, top=0.95, left=0.15, right=1.6,
                    wspace=0.1, hspace=0.15)
cmap = plt.get_cmap('gist_earth_r')
cmap.set_over('navy')
cmap.set_under('white')
gridY, gridX = np.mgrid[0:1000:31 * 1j, -90:90:31 * 1j]
for i, ax in enumerate(axs.flatten(order='F')):
    if i < len(axs.flatten()) / 2:
        cs = np.random.default_rng().integers(101, size=(31, 31))
        pcm = ax.pcolormesh(gridX, gridY, cs, vmin=0, vmax=100, cmap=cmap)
    else:
        cs = np.random.default_rng().integers(6, size=(31, 31))
        pcm = ax.pcolormesh(gridX, gridY, cs, vmin=0, vmax=5, cmap=cmap)
    if i == len(axs.flatten()) / 2 - 1:
        fig.colorbar(pcm, ax=axs[:, :2], shrink=0.6, location='bottom',
                     pad=0.05, ticks=np.linspace(0, 100, 21))
    elif i == len(axs.flatten()) - 1:
        fig.colorbar(pcm, ax=axs[:, 2:], location='bottom', shrink=0.6,
                     pad=0.05, ticks=np.linspace(0, 5, 21))
ax.set_xticks([-90, -60, -30, 0, 30, 60, 90])
ax.set_xticklabels(['90S', '60S', '30S', '0', '30N', '60N', '90N'])
ax.invert_yaxis()
fig.savefig('so.png', bbox_inches='tight')

在此处输入图片说明

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