The problem is that the colors for a contourf
plot are taken from the middle of the respecive interval. To replicate the same behaviour for a pcolor
plot, you need to select the colors not simply as equally spaced range from the colormap (colors = cmap(range(cmap.N))
), but as the two endpoints of the map and the respective means between the level boundaries.
cnorm = plt.Normalize(vmin=levels[0],vmax=levels[-1])
clevels = [levels[0]] + list(0.5*(levels[1:]+levels[:-1])) + [levels[-1]]
colors=plt.cm.RdYlBu(cnorm(clevels))
Complete code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
a = np.arange(12)[:,np.newaxis] * np.ones(8)
levels = np.arange(1.5, 10, 2)
fig, (ax,ax2) = plt.subplots(ncols=2)
ax.set_title("contourf")
cf = ax.contourf(a, levels=levels, cmap='RdYlBu', extend='both') #,
fig.colorbar(cf, ax=ax)
##### pcolormesh
cnorm = plt.Normalize(vmin=levels[0],vmax=levels[-1])
clevels = [levels[0]] + list(0.5*(levels[1:]+levels[:-1])) + [levels[-1]]
colors=plt.cm.RdYlBu(cnorm(clevels))
cmap, norm = matplotlib.colors.from_levels_and_colors(levels, colors, extend='both')
cf = ax2.pcolormesh(a, cmap=cmap, norm=norm)
ax2.set_title("pcolormesh")
fig.colorbar(cf,ax=ax2)
plt.tight_layout()
plt.show()
To better understand the solution, you may want to replace the line cmap, norm = matplotlib.colors.from_levels_and_colors(levels, colors, extend='both')
by
norm=matplotlib.colors.BoundaryNorm(levels, ncolors=len(levels)-1)
cmap = matplotlib.colors.ListedColormap(colors[1:-1], N=len(levels)-1)
cmap.set_under(colors[0])
cmap.set_over(colors[-1])
cmap.colorbar_extend = "both"
This may make it clearer, where the colors and the colormap eventually used originate from.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…