Matplotlib自定义色图边界匹配向量间隔及渐变色图适配问题
实现方案
1. 按区间样本量调整色条间隔的方法
你要的效果确实不能通过spacing='proportional'实现,该参数仅能让色条间隔和数值边界的大小成正比。要让色条段长度匹配对应区间的样本数量,需要两步操作:
- 首先统计你预设的每个特征区间内的样本数量,计算各区间样本量占总样本的比例
- 自定义数值到色条位置的映射规则,让每个颜色段在色条上的长度和对应区间的样本占比一致
修改后的可运行代码如下:
import matplotlib.pyplot as plt import numpy as np import matplotlib.colors as colors fig = plt.figure(figsize=(10,7)) ax = fig.add_subplot() category = [0,0,0,0.1,0.4,0.9,1.5] r = np.random.uniform(size=[len(category)*100]).reshape(len(category),100) # 原始特征区间边界 bounds = np.array([0, 0.3, 0.5, 1.5]) # 统计每个区间内的样本数量 counts = [] for i in range(len(bounds)-1): cnt = np.sum((np.array(category) >= bounds[i]) & (np.array(category) < bounds[i+1])) counts.append(cnt) counts = np.array(counts) # 计算按样本量分配的色条位置比例 cum_counts = np.cumsum([0] + list(counts)) norm_pos = cum_counts / cum_counts[-1] # 自定义数值到色条位置的映射函数 def value_to_norm(x): # 定位x所属的区间 idx = np.searchsorted(bounds, x, side='right') - 1 idx = np.clip(idx, 0, len(bounds)-2) # 区间内线性映射到对应色条段范围 x_low, x_high = bounds[idx], bounds[idx+1] pos_low, pos_high = norm_pos[idx], norm_pos[idx+1] return pos_low + (x - x_low) / (x_high - x_low) * (pos_high - pos_low) # 生成自定义Norm规则 norm = colors.FuncNorm((value_to_norm, lambda x: x), vmin=0, vmax=1) # 此处使用分段色图,也可替换为任意连续渐变色图 cmap = colors.ListedColormap(['green', 'blue', 'red']) scalar_map = plt.cm.ScalarMappable(norm=norm, cmap=cmap) scalar_map.set_array([]) for no, cat in enumerate(category): ax.plot(r[no][r[no]>0.1],no*np.ones(100)[r[no]>0.1],'o',color=scalar_map.to_rgba(value_to_norm(cat))) # 绘制色条,设置刻度对应原始边界值 cbar = fig.colorbar(scalar_map, ax=ax, pad=0.01, ticks=norm_pos) cbar.set_ticklabels(bounds) plt.show()
2. 连续渐变色图适配说明
这种自定义边界逻辑完全可以用于非分段的渐变色图,仅需要把代码里的ListedColormap替换为任意内置连续色图即可,比如plt.cm.viridis、plt.cm.plasma等,数值到颜色的映射会自动适配你定义的样本量权重间隔。
内容的提问来源于stack exchange,提问作者SerKo
相关产品推荐
相关产品推荐

