Matplotlib中如何获取/设置无空白colorbar的正确格式化y轴刻度
Matplotlib colorbar配置异常修复方案
问题表现
- 调用
get_ticks()获取的色条y轴刻度与实际数据范围不符:测试数据最小值为17.15116279,但返回的刻度最小值为15;使用该返回值调用.set_ticks()设置刻度后,色条颜色映射错位,且出现多余空白区域。 - 若不执行
cbar.ax.yaxis.set_ticks(vals)语句,色条显示效果正常,但会触发警告:UserWarning: FixedFormatter should only be used together with FixedLocator。
已验证无效的排查方向
- 直接传入
mtick.PercentFormatter作为colorbar的format参数可规避问题,但无法灵活自定义刻度标签格式。 - 获取刻度前执行
fig.draw_without_rendering(),得到的刻度值仍不符合数据范围,还会导致色条出现第二块空白区域。 - 问题根因初步分析:默认生成的刻度并非全部落在
vmin/vmax定义的视图范围内,首尾刻度可能超出数据区间;手动设置刻度时坐标轴会自动扩展视图范围适配所有传入刻度,刻度超出vmin/vmax就会产生空白。但手动将首尾刻度替换为vmin、vmax,并将首尾刻度标签设为空字符串,显示效果仍未达预期。
问题复现代码
import geopandas as gpd # version 0.11.0 import matplotlib.pyplot as plt # version 3.5.2 import matplotlib.colors as clr from matplotlib import colorbar from matplotlib.colors import Normalize # tbv colorbar from matplotlib import cm import matplotlib.ticker as mtick cmap = clr.LinearSegmentedColormap.from_list('custom blue', ["#fce19c", "#c4ddee"], N=400) world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) world = world[(world.pop_est>0) & (world.name!="Antarctica")] vals = [22.36958444, 29.21348315, 30.74534161, 37.42331288, 20., 19.31407942, 26.08695652, 26.36165577, 25.0, 17.79279279, 17.15116279, 19.60784314] world = world[:len(vals)] world['gdp_per_cap'] = vals fig, ax = plt.subplots(1, 1) ax = world.plot(column='gdp_per_cap', ax=ax, legend=False, cmap=cmapgeelblauw) from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.1) vmin = world['gdp_per_cap'].min() vmax = world['gdp_per_cap'].max() norm = Normalize(vmin=vmin, vmax=vmax) n_cmap = cm.ScalarMappable(norm=norm, cmap=cmap) n_cmap.set_array([]) cbar = fig.colorbar(n_cmap, cax=cax) print(cax==cbar.ax) # True vals = cbar.ax.get_yticks() print(vals) cbar.ax.yaxis.set_ticks(vals) cbar.ax.set_yticklabels(['{:,.0%}'.format(x/100) for x in vals]) plt.show()
修复方案
问题核心逻辑:直接调用set_yticklabels会强制为坐标轴绑定FixedFormatter,但此时坐标轴使用的不是FixedLocator,因此触发匹配警告;而直接取用默认生成的全量刻度重新设置时,超出vmin/vmax范围的首尾刻度会强制坐标轴扩展视图范围,最终导致色条错位、出现空白。
修复操作步骤:
- 获取默认生成的原始刻度后,过滤掉所有落在
[vmin, vmax]区间外的刻度值;如果需要展示数据最值对应的刻度,可将vmin、vmax追加到有效刻度列表后排序。 - 显式为y轴设置
FixedLocator绑定筛选后的有效刻度,保证locator和formatter匹配,从根源消除警告,同时避免超界刻度扩展坐标轴范围。
核心修复代码:
cbar = fig.colorbar(n_cmap, cax=cax) # 过滤超界的无效刻度 raw_ticks = cbar.ax.get_yticks() valid_ticks = [t for t in raw_ticks if vmin <= t <= vmax] # 按需追加最值刻度 # valid_ticks = sorted(valid_ticks + [vmin, vmax]) # 显式设置FixedLocator匹配后续的FixedFormatter cbar.ax.yaxis.set_major_locator(mtick.FixedLocator(valid_ticks)) # 自定义刻度标签格式,可按需调整格式逻辑 cbar.ax.set_yticklabels(['{:,.0%}'.format(x/100) for x in valid_ticks])
内容的提问来源于stack exchange,提问作者Wouter
相关产品推荐
相关产品推荐

