如何用plt.contourf()绘制量级差异大的等高线及相关问题
等高线绘制问题解答
问题背景
我希望用plt.contourf()绘制等高线以达到目标图效果,但实际绘制结果不符。我的数据特点:
- 量级差异极大,范围从10-11到105
- 高程点数量为80*80
我的疑问:
contourf()能否达到示例图的精度?- 仅80*80点能否实现目标效果?
- 如何在
colorbar()中设置自定义对数刻度范围?
我的代码
def draw_contour(): np_array=np.load("terrain.npy") x,y=np.meshgrid(np.linspace(0,80,80),np.linspace(0,80,80)) plt.contourf(x,y,np_array[:,0].reshape(80,80),levels=100000,locator=ticker.LogLocator(),alpha=1,linestyles='--',cmap='terrain') plt.colorbar(label='Elevation') plt.xlabel('X') plt.ylabel('y') plt.show() print('end') if __name__=='__main__': draw_contour()
部分数据示例
1.599047500000000004e-09、1.313549499999999921e-09 ... 5.243679999999999743e-07
问题解答
1. contourf()能否达到示例图的精度?
可以,但你的代码存在几个影响效果的问题:
contourf()是填充等高线,linestyles参数对它无效(该参数仅适用于contour()),多余参数会干扰渲染逻辑- 设置
levels=100000完全没必要,对数刻度下这么多级别会导致计算量暴增,且肉眼根本分辨不出差异,反而容易出现渲染异常 - 直接用
LogLocator但未处理数据中的极小值(比如10^-11),可能出现刻度显示异常或填充断层
修正思路:保留对数刻度定位器,合理设置levels数量(20-50足够),移除无效参数,同时过滤数据中小于等于0的数值(对数刻度不支持负数)。
2. 仅80*80点能否实现目标效果?
取决于目标图的细节要求:
- 如果目标图是宏观趋势展示,80*80的分辨率足够,能呈现整体的高低分布
- 如果目标图需要精细的局部地形细节,80*80的点密度就不够了——相邻点间距较大,插值生成的等高线会比较粗糙,无法还原小尺度地形起伏
如果必须用现有数据,可以通过两种方式优化:
- 在
contourf()中设置interpolation='bilinear'或interpolation='bicubic'提升渲染平滑度 - 先用
scipy.interpolate.griddata对原始数据做插值,提升分辨率后再绘图
3. 如何在colorbar()中设置自定义对数刻度范围?
可以通过以下方式实现,结合代码示例:
import matplotlib.pyplot as plt import numpy as np from matplotlib.ticker import LogLocator def draw_contour(): np_array = np.load("terrain.npy") data = np_array[:,0].reshape(80,80) # 过滤负数和0,避免对数计算报错 data[data <= 0] = np.nan x,y = np.meshgrid(np.linspace(0,80,80), np.linspace(0,80,80)) # 自定义对数刻度范围:1e-10 到 1e5 vmin = 1e-10 vmax = 1e5 # 生成对数间距的等高线级别 levels = np.logspace(np.log10(vmin), np.log10(vmax), num=30) cf = plt.contourf(x, y, data, levels=levels, locator=LogLocator(base=10), cmap='terrain', alpha=1) # 设置colorbar的自定义刻度 cbar = plt.colorbar(cf, label='Elevation') # 手动指定刻度位置 cbar.set_ticks([1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 1, 1e2, 1e4, 1e5]) # 自定义刻度显示文本 cbar.set_ticklabels(['1e-10', '1e-8', '1e-6', '1e-4', '1e-2', '1', '100', '10000', '1e5']) plt.xlabel('X') plt.ylabel('Y') plt.show() print('end') if __name__=='__main__': draw_contour()
如果数据有部分超出自定义范围,可以给colorbar添加extend='both'参数,显示超出范围的颜色块,明确提示数据边界。
内容的提问来源于stack exchange,提问作者user24093602
相关产品推荐
相关产品推荐

