Matplotlib contourf自定义配色时双向拓展colorbar颜色重复问题
使用contourf绘图时设置了自定义配色方案,且将colorbar设置为两端拓展模式,但实际输出中色条两端的最后两个区间颜色相同(如图所示),期望每个区间都能匹配预设的不同颜色。
所用脚本如下:import matplotlib.pyplot as plt import matplotlib.colors import numpy as np from mpl_toolkits.basemap import Basemap val=np.random.random((37,97)) theLats=np.arange(0,90.3,2.5) theLons=np.arange(-50,190.3,2.5) xx, yy = np.float32(np.meshgrid(theLons, theLats)) m = Basemap(projection='cyl', resolution='l', llcrnrlat=5, llcrnrlon=65, urcrnrlat=40, urcrnrlon=100) m.drawcoastlines() parallels = np.arange(-90.,90,20.) m.drawparallels(parallels,labels=[1,0,0,0],fontsize=10) meridians = np.arange(0.,360.,20.) m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10) x, y = m(xx, yy) colors=['red', 'darkorange', 'goldenrod','gold', 'lightgreen','limegreen','aquamarine','aqua','blue'] cm = matplotlib.colors.ListedColormap(colors) clevs = np.arange(0.2,.8,0.1) cs = m.contourf(x,y,val,clevs,cmap=cm,extend='both') cbar = m.colorbar(cs,location='right',pad="5%") plt.show()问题示例图:
原因分析
- 你定义的
clevs = np.arange(0.2,.8,0.1)共生成6个边界值,对应5个普通数值区间,配合extend='both'参数,总共有<0.2、5个中间区间、>0.7共7个需要配色的区间。 - 你传入的自定义配色列表有9个颜色,matplotlib默认会自动从给定颜色中均匀采样映射到7个区间,导致相邻区间出现重复颜色,就是你看到的色条两端区间颜色一致的问题。
解决方案
通过BoundaryNorm明确绑定区间和颜色的映射关系,避免matplotlib自动采样取色即可解决问题,以下是两种适用场景的修改方案:
方案1:保留原有等级范围,适配9个自定义颜色
如果不需要调整clevs的数值范围,直接明确颜色映射规则即可:
import matplotlib.pyplot as plt import matplotlib.colors import numpy as np from mpl_toolkits.basemap import Basemap val=np.random.random((37,97)) theLats=np.arange(0,90.3,2.5) theLons=np.arange(-50,190.3,2.5) xx, yy = np.float32(np.meshgrid(theLons, theLats)) m = Basemap(projection='cyl', resolution='l', llcrnrlat=5, llcrnrlon=65, urcrnrlat=40, urcrnrlon=100) m.drawcoastlines() parallels = np.arange(-90.,90,20.) m.drawparallels(parallels,labels=[1,0,0,0],fontsize=10) meridians = np.arange(0.,360.,20.) m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10) x, y = m(xx, yy) colors=['red', 'darkorange', 'goldenrod','gold', 'lightgreen','limegreen','aquamarine','aqua','blue'] clevs = np.arange(0.2,.8,0.1) # 取列表第一个颜色作为小于0.2的拓展色,最后一个作为大于0.7的拓展色,中间7个取5个对应普通区间 cm = matplotlib.colors.ListedColormap(colors[1:6]) cm.set_under(colors[0]) cm.set_over(colors[-1]) # 明确绑定区间和颜色 norm = matplotlib.colors.BoundaryNorm(clevs, ncolors=cm.N, extend='both') cs = m.contourf(x,y,val,clevs,cmap=cm,norm=norm,extend='both') cbar = m.colorbar(cs,location='right',pad="5%") plt.show()
方案2:调整等级范围,用完9个自定义颜色
如果你希望9个颜色全部对应不同的数值区间,调整clevs的边界数量即可:
# 其他代码和上述一致,仅修改clevs和colormap定义部分 colors=['red', 'darkorange', 'goldenrod','gold', 'lightgreen','limegreen','aquamarine','aqua','blue'] cm = matplotlib.colors.ListedColormap(colors) # 8个边界对应7个普通区间,加两端拓展共9个区间,刚好匹配9个颜色 clevs = np.arange(0.1, 0.9, 0.1) norm = matplotlib.colors.BoundaryNorm(clevs, ncolors=cm.N, extend='both') cs = m.contourf(x,y,val,clevs,cmap=cm,norm=norm,extend='both') cbar = m.colorbar(cs,location='right',pad="5%") plt.show()
内容的提问来源于stack exchange,提问作者Aristocrat
相关产品推荐
相关产品推荐


