在进行科研绘图中,我们常常会有这样一个需求:①对多个图层采用相同的配色方案并依次导出;②把导出的各子图拼成一个大图像;③在大图中插入统一的目标色带。
前两步通常用 ArcGIS Pro 就可以搞定了。而在第三步时,ArcGIS Pro 的布局中虽也能生成色带,但有以下两个重要缺陷:1)生成离散性变量(如 Natural Breaks 等方法自动生成的间隔)会逐个展示颜色斑块与对应的范围,显得冗余而杂乱。如果有大于7个变量的话,会占用很大一块地方,造成画布空间的浪费(见下图);2)哪怕能够生成连续的色带,ArcGIS Pro 对于色带辅助信息(如刻度样式,上下标、符号等特殊文本,边框样式等)的自定义程度也很薄弱。
这两个缺陷难以在 ArcGIS 中克服。因此,我想使用 matplotlib 直接为离散间隔数据绘制 colorbar,经一番探索后取得了理想的效果。绘制流程如下所述:
引入包
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.colors import ListedColormap
定义色带与数据范围
首先是定义色带与数据范围。为了展示绘制多个、不规则的离散间隔色带,我使用截图软件从经典的“蓝-黄-红”色带中提取了 32 个颜色,将结果保存在了clist
变量中。它们对应于vlist
变量中的 33 个数据标签(首、尾、加 31 个间隔)。
color_record = ["599FCD", "68A5C9", "76ABC6", "81B0C1", "8BB7BE",
"96BCBA", "A1C1B7", "AAC8B2", "B4CFAC", "BED4A8",
"C5DAA4", "CEE1A1", "D8E69C", "DFEC97", "E7F393",
"EFF88E", "F2F689", "F3EA81", "F2E17B", "F2D675",
"F0CB6E", "F1C068", "EDB460", "EDA95B", "ED9E56",
"EA924F", "E98649", "E67A43", "E46E3D", "E15F38",
"DF5132", "DD3F2F"]
clist = ["#" + i for i in color_record]
vlist = [0, 263, 555, 837, 1175, 1523, 1832, 2105, 2424, 2776, 3181, 3622, 4106, 4571, 4914,
5314, 5784, 6221, 6593, 7086, 7664, 8154, 8659, 9139, 9600, 10073, 10483, 10905,
11379, 11853, 12520, 13189, 13450]
单独绘制 colorbar
通过ListedColormap()
从clist
这个列表中创建 colormap 对象,然后通过mpl.colors.BoundaryNorm()
对vlist
变量创建色带的 index,绘制好色带的 ticks
与 ticklabels
。
这里有几个注意点。一是要根据实际情况设置好图像长宽;二是要通过设置spacing='proportional'
来控制颜色间隔与数据间隔相匹配;三是在标题中设定上标格式的写法。最终结果展示如下:
fig, ax = plt.subplots(figsize=(18, 0.5), dpi=300)
cmap = ListedColormap(clist)
norm = mpl.colors.BoundaryNorm(vlist, len(vlist))
fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap), ticks = vlist,
cax = ax, spacing = "proportional", orientation='horizontal')
ax.set_xticklabels(vlist, rotation=-45)
ax.set_title("Area (unit: $\mathregular{m^2}$)")
plt.savefig("result.png", dpi=300, transparent=False, facecolor='white', bbox_inches='tight')
相关参考
https://matplotlib.org/stable/tutorials/colors/colorbar_only.html
2024年11月14日 04:05
博主太厉害了!
2024年10月19日 14:24
哈哈哈,写的太好了https://www.cscnn.com/
2024年09月23日 08:54
看的我热血沸腾啊