Python-matplotlib 空间栅格数据可视化

2020-08-10 17:44:19 浏览数 (1)

python-matplotlib 在地理空间数据可视化绘制方面也还是有一定的优势的,为更新colorbar绘制应用范围,我们把gis,遥感等专业的需要常做的空间可视化图,试着用matplotlib 进行绘制(也是小伙伴提出:用arcgis等软件在对多子图绘制colorbar时,存在无法共用的情况,即软件是一幅一幅的出图,导致汇总对比时,colorbar不统一,影响对比分析)

01. 数据处理

本次的tif数据需要用到专门的库进行读取,即使用gdal进行tif数据读取(gdal不仅包括tif数据读取,还包括投影转换、地理信息读取等功能,也是处理空间数据最常用的python库,如果只是单单读取tif文件数据,tifffile等包也能很好处理)。导入如下:

代码语言:javascript复制
from osgeo import gdal

读取一幅tif影像,分别获取其行、列和通道数:

代码语言:javascript复制
tif01 = r"F:DataCharmPython-matplotlib 空间数据可视化mod16a2200001.et_32767_0.1.tif"
tifdata01 = gdal.Open(tif01)
rows = tifdata01.RasterXSize
columns = tifdata01.RasterYSize
bands = tifdata01.RasterCount
rows,columns,bands

结果如下:

我们还可以获取这副tif数据如 地理信息、投影信息等数据,这也是处理空间数据用的最多的数据集系列。获取如下:

代码语言:javascript复制
#获取地理信息
img_geotrans = tifdata01.GetGeoTransform()
#获取投影信息
img_proj = tifdata01.GetProjection()

这里用不到此类数据,就不做过多描述,后面涉及到坐标转换、投影转换等操作会详细讲解。

获取数组数据,用到如下代码:

代码语言:javascript复制
#获取对应的数据
tif_data01 = tifdata01.ReadAsArray(0,0,samples,lines)
tif_data01,tif_data01.shape

结果如下:

可以看到数组中有很多nan值,而numpy对于数组梳理操作还是比较方便的。这里我们需要求取每个tif数组的最小值和最大值,而存在nan值的情况下,numpy也有对应的处理方式,十分方便。如下:

代码语言:javascript复制
#求取除nan值外得最小值
np.nanmin(tif_data01)
#求取除nan值外得最大值
np.nanmax(tif_data01)

这一步非常关键,对后期统一颜色条(colorbar)至关重要,下面构建列表,存储每个tif数据的最大、最小值。如下:

代码语言:javascript复制
min_list = []
max_list = []

min_list.append(np.nanmin(tif_data01))
min_list.append(np.nanmin(tif_data02))
min_list.append(np.nanmin(tif_data03))
data_min = np.min(min_list)

max_list.append(np.nanmax(tif_data01))
max_list.append(np.nanmax(tif_data02))
max_list.append(np.nanmax(tif_data03))

data_max = np.max(max_list)

最终获取三幅tif数据的最小、最大值如下:

02. 数据可视化

在对数据进行可视化展示,主要使用matplotlib的imshow()方法,完整代码如下:

代码语言:javascript复制
fig,ax = plt.subplots(1, 3,figsize = (12,5),sharey=True)

vmin = data_min
vmax = data_max
#Normalize()跟归一化没有任何关系,函数的作用是将颜色映射到vmin-vmax上,
#颜色表/颜色柱的起始和终止分别取值vmin和vmax
norm = Normalize(vmin = vmin,vmax = vmax)
extent = (0,1,0,1)

im1 = ax[0].imshow(tif_data01,extent = extent,norm = norm,cmap = 'jet')
ax[0].set_axis_off()
im2 = ax[1].imshow(tif_data02,extent = extent,norm = norm,cmap = 'jet')
ax[1].set_axis_off()
im3 = ax[2].imshow(tif_data03,extent = extent,norm = norm,cmap = 'jet')
ax[2].set_axis_off()
ax[2].text(.8,-.02,'nVisualization by DataCharm',transform = ax[2].transAxes,
        ha='center', va='center',fontsize = 10,color='black')

fig.subplots_adjust(right=0.9)

#前面三个子图的总宽度为全部宽度的 0.9;剩下的0.1用来放置colorbar
fig.subplots_adjust(right=0.9)
position = fig.add_axes([0.95, 0.22, 0.015, .55 ])#位置[左,下,右,上]
cb = fig.colorbar(im3, cax=position)

#设置colorbar标签字体等
colorbarfontdict = {"size":15,"color":"k",'family':'Times New Roman'}
cb.ax.set_title('Values',fontdict=colorbarfontdict,pad=8)
cb.ax.set_ylabel('EvapotTranspiration(ET)',fontdict=colorbarfontdict)
cb.ax.tick_params(labelsize=11,direction='in')
#cb.ax.set_yticklabels(['0','10','20','30','40','50','>60'],family='Times New Roman')
fig.suptitle('One Colorbar for Multiple Map Plot ',size=22,family='Times New Roman',
             x=.55,y=.9)
plt.savefig(r'F:DataCharmPython-matplotlib 空间数据可视化map_colorbar.png',dpi = 600,
            bbox_inches='tight',width = 12,height=4)
plt.show()

其中,imshow()方法中设置了norm参数和extent参数,其中norm参数决定colorbar的统一设置,extent参数可以如下图进行解释:

未设置extent参数:

设置extent参数:

代码语言:javascript复制
ax.imshow(tif_data02,cmap = 'jet',extent = (0,1,0,1))

可以明显看到坐标轴的范围发生了明显改变。当然extent参数还可以设置其他数值,进行不同效果的展示。

最终绘制的效果如下:

该图有可能还缺少如横纵坐标等绘图参数,因为原始数据的坐标系需要转换成常规的经纬度信息,在这里就不进行展示了,后面的空间可视化绘制教程中会专门进行讲解。

03. 总结

这算是空间数据可视化绘制的第一篇推文了,感谢我的同学“小太阳”提供的数据。这也算是gis等专业同学经常需要绘制的学术图表之一,接下来可视化绘制教程也会偏空间数据居多,当然,也会根据小伙伴的提问进行其他专题的讲解,最终目的,还是希望我的教程能能够帮助到您

0 人点赞