Matplotlib散点图与Colorbar颜色不匹配的实现方法
问题核心根源
散点与配套色条不匹配的本质是着色逻辑违背Matplotlib的色阶映射规则:
- 原代码提前通过
data['river1'].map(cmap)将径流占比数值硬映射为具体RGB颜色,再传入scatter的c参数 - 当
c参数接收已完成渲染的颜色序列时,Matplotlib会直接跳过自动着色、数值归一化流程,你之前设置的vmin=0、vmax=1参数完全失效 - 后续生成的Colorbar没有与真实径流占比数值的绑定关系,会基于无意义的内部缓存值生成刻度,最终出现散点颜色与色条刻度完全错位的问题
注意:当c参数接收RGB/RGBA格式的颜色序列时,Matplotlib会完全跳过自动着色和归一化流程,此时生成的色条不具备数值匹配意义,必然出现色值错位
修复操作要点
- 不要提前对传入
c的数值做手动色图映射,直接将原始径流占比数值传入c参数,由Matplotlib自动完成「数值→色图颜色」的绑定 - 将自定义色图通过
scatter的cmap参数传入,而非提前手动映射每个点的颜色 - 保留明确的
vmin/vmax范围定义,确保数值到颜色的映射区间与色条刻度完全对齐
修正后的可运行代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.basemap import Basemap data = pd.read_csv('data ocean.csv', delimiter=';') fig = plt.figure(figsize=(23, 7)) m = Basemap( width=1500000, height=1000000, projection='stere', lat_ts=73, lat_0=73, lon_0=127, resolution='l' ) m.drawcoastlines() m.drawmapboundary() m.fillcontinents(color='red') # 绘制经纬网格 m.drawparallels(np.arange(60., 80., 5.)) m.drawmeridians(np.arange(0., 180., 10.)) # 直接定义色图对象,不做提前映射 cmap = plt.cm.get_cmap('Dark2_r') x, y = m(np.array(data['Long1']), np.array(data['Lat1'])) # 传入原始数值作为着色依据,绑定vmin/vmax与色图 pic = plt.scatter( x, y, marker='o', vmin=0, vmax=1, s=50, c=data['river1'], cmap=cmap ) plt.title('доля речных вод, 2015 ', fontsize='15') plt.colorbar(pic) # 保存逻辑移到show之前,避免画布缓存释放导致保存空白 fig.savefig('1.png', dpi=fig.dpi) plt.show()
常见踩坑提示
- 如果你的
river1字段是离散分类值而非连续占比数值,需要将vmin/vmax调整为匹配分类索引的范围,不要硬设为0-1 - 不需要手动设置离散色图的长度匹配样本数,Matplotlib会根据传入的数值范围对色图做线性映射,不会出现色值错位
- 原代码中
plt.draw()放在plt.show()之后会触发图像缓冲释放,容易导致保存的图片为空白,可移除该冗余调用
内容的提问来源于stack exchange,提问作者hazel
相关产品推荐
相关产品推荐

