写在前面
上次交了作业(全国气温分布图)之后,老师开始让自己摸索处理数据的方法。为了这周先交一个成果上去(已经拖了两周了),决定画一个四季分布图和一个时序图,用两篇文章来记录。
下面的0.可以忽略
0.批量修改文件后缀(如txt文件 —>xlsx)(此步骤可忽略)
(此方法修改后的文件能用wps打开,但其他地方不一定能用)
用记事本创建一个新的txt文件,写入ren *.txt *.xlsx(注意是英文空格)
保存为.bat文件,保存在与需要修改后缀的文件同一目录下
保存后运行,即可看到后缀已修改
SOS: 修改后的excel表格无法用office打开,显示已损坏,目前没有解决方案......
用python读取修改后的表格也会报错Excel file format cannot be determined, you must specify an engine manually.
下面开始正文 —— 画2002.3-.2的全国站点降水四季分布图
1.数据处理
1-1 将三个月每天的站点数据合并到一个文本文件中
用记事本创建一个新的txt文件,写入
for %%i in (*.txt) do type %%i>>1.txt(注意是英文空格)(1.txt为合并后文件名称)
即for %%i in (所有.这种格式的文件) do type %%i>>导出后的文件名称.文件格式
与要合并的txt文件保存在同级目录下,运行就可以了
1-2用excel读取、计算每个站点三个月降水的平均值(excel处理方法见上一篇文章)
2.绘制春夏秋冬分布图直接上代码
from pickletools import long4from pkgutil import extend_pathimport matplotlibimport matplotlib.pyplot as pltimport numpy as npfrom cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatterimport matplotlib.ticker as mtickerimport cartopy.crs as ccrsimport cartopy.feature as cfeatureimport pandas as pdfrom cartopy.io import shapereader as shpreaderdf1 = pd.read_excel(r"D:\春 终版.xlsx")df2 = pd.read_excel(r"D:\夏 终.xlsx")df3 = pd.read_excel(r"D:\秋 终.xlsx")df4 = pd.read_excel(r"D:\冬 终.xlsx")lat1 = df1['Lat']lon1 = df1['Lon']pre1 = df1['平均值项:PRE_Time_']lat2 = df2['Lat']lon2 = df2['Lon']pre2 = df2['平均值项:PRE_Time_']lat3 = df3['Lat']lon3 = df3['Lon']pre3 = df3['平均值项:PRE_Time_']lat4 = df4['Lat']lon4 = df4['Lon']pre4 = df4['平均值项:PRE_Time_']# 建立画布fig2 = plt.figure(figsize=(20, 12))norm = matplotlib.colors.Normalize(vmin=0, vmax=40)proj = ccrs.PlateCarree(central_longitude=105)leftlon, rightlon, lowerlat, upperlat = (70, 140, 15, 55) # 根据上下限确定范围,至少为10°# 春 ------------------------------------------------------------------------------------#左 底 宽 高f2_ax1 = fig2.add_axes([0.2, 0.35, 0.45, 0.225], projection=proj)# 在画布的绝对坐标建立子图f2_ax1.set_extent([leftlon, rightlon, lowerlat, upperlat],crs=ccrs.PlateCarree())# 海岸线,50m精度f2_ax1.add_feature(cfeature.COASTLINE.with_scale('50m'))# 湖泊数据(但是这个貌似只画了比较大的湖泊,比如贝湖巴湖)f2_ax1.add_feature(cfeature.LAKES, alpha=0.5)# 以下6条语句是定义地理坐标标签格式f2_ax1.set_xticks(np.arange(leftlon, rightlon+10, 10),crs=ccrs.PlateCarree())f2_ax1.set_yticks(np.arange(lowerlat, upperlat+10, 10),crs=ccrs.PlateCarree())lon_formatter = LongitudeFormatter()lat_formatter = LatitudeFormatter()f2_ax1.xaxis.set_major_formatter(lon_formatter)f2_ax1.yaxis.set_major_formatter(lat_formatter)f2_ax1.set_title('Spr', loc='left', fontsize=10)# 读取shp文件china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()# 绘制中国国界省界九段线等等f2_ax1.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)# 添加南海,实际上就是新建一个子图覆盖在之前子图的右下角f2_ax2 = fig2.add_axes([0.505, 0.353, 0.04, 0.07], projection=proj)f2_ax2.set_extent([105, 125, 0, 25], crs=ccrs.PlateCarree())f2_ax2.add_feature(cfeature.COASTLINE.with_scale('50m'))china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()f2_ax2.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)f1 = f2_ax1.scatter(lon1, lat1, s=2, c=pre1, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)f2 = f2_ax2.scatter(lon1, lat1, s=2, c=pre1, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)# 夏-------------------------------------------------------------------------------------f2_ax3 = fig2.add_axes([0.5, 0.35, 0.45, 0.225], projection=proj)# 在画布的绝对坐标建立子图f2_ax3.set_extent([leftlon, rightlon, lowerlat, upperlat],crs=ccrs.PlateCarree())# 海岸线,50m精度f2_ax3.add_feature(cfeature.COASTLINE.with_scale('50m'))# 湖泊数据(但是这个貌似只画了比较大的湖泊,比如贝湖巴湖)f2_ax3.add_feature(cfeature.LAKES, alpha=0.5)# 以下6条语句是定义地理坐标标签格式f2_ax3.set_xticks(np.arange(leftlon, rightlon+10, 10),crs=ccrs.PlateCarree())f2_ax3.set_yticks(np.arange(lowerlat, upperlat+10, 10),crs=ccrs.PlateCarree())lon_formatter = LongitudeFormatter()lat_formatter = LatitudeFormatter()f2_ax3.xaxis.set_major_formatter(lon_formatter)f2_ax3.yaxis.set_major_formatter(lat_formatter)f2_ax3.set_title('Sum', loc='left', fontsize=10)# 读取shp文件china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()# 绘制中国国界省界九段线等等f2_ax3.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)# 添加南海,实际上就是新建一个子图覆盖在之前子图的右下角f2_ax4 = fig2.add_axes([0.805, 0.353, 0.04, 0.07], projection=proj)f2_ax4.set_extent([105, 125, 0, 25], crs=ccrs.PlateCarree())f2_ax4.add_feature(cfeature.COASTLINE.with_scale('50m'))china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()f2_ax4.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)f3 = f2_ax3.scatter(lon2, lat2, s=2, c=pre2, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)f4 = f2_ax4.scatter(lon2, lat2, s=2, c=pre2, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)# 秋-------------------------------------------------------------------------------------f2_ax5 = fig2.add_axes([0.2, 0.05, 0.45, 0.225], projection=proj)# 在画布的绝对坐标建立子图f2_ax5.set_extent([leftlon, rightlon, lowerlat, upperlat],crs=ccrs.PlateCarree())# 海岸线,50m精度f2_ax5.add_feature(cfeature.COASTLINE.with_scale('50m'))# 湖泊数据(但是这个貌似只画了比较大的湖泊,比如贝湖巴湖)f2_ax5.add_feature(cfeature.LAKES, alpha=0.5)# 以下6条语句是定义地理坐标标签格式f2_ax5.set_xticks(np.arange(leftlon, rightlon+10, 10),crs=ccrs.PlateCarree())f2_ax5.set_yticks(np.arange(lowerlat, upperlat+10, 10),crs=ccrs.PlateCarree())lon_formatter = LongitudeFormatter()lat_formatter = LatitudeFormatter()f2_ax5.xaxis.set_major_formatter(lon_formatter)f2_ax5.yaxis.set_major_formatter(lat_formatter)f2_ax5.set_title('Fal', loc='left', fontsize=10)# 读取shp文件china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()# 绘制中国国界省界九段线等等f2_ax5.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)# 添加南海,实际上就是新建一个子图覆盖在之前子图的右下角f2_ax6 = fig2.add_axes([0.505, 0.053, 0.04, 0.07], projection=proj)f2_ax6.set_extent([105, 125, 0, 25], crs=ccrs.PlateCarree())f2_ax6.add_feature(cfeature.COASTLINE.with_scale('50m'))china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()f2_ax6.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)f5 = f2_ax5.scatter(lon3, lat3, s=2, c=pre3, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)f6 = f2_ax6.scatter(lon3, lat3, s=2, c=pre3, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)# 冬-------------------------------------------------------------------------------------f2_ax7 = fig2.add_axes([0.5, 0.05, 0.45, 0.225], projection=proj)# 在画布的绝对坐标建立子图f2_ax7.set_extent([leftlon, rightlon, lowerlat, upperlat],crs=ccrs.PlateCarree())# 海岸线,50m精度f2_ax7.add_feature(cfeature.COASTLINE.with_scale('50m'))# 湖泊数据(但是这个貌似只画了比较大的湖泊,比如贝湖巴湖)f2_ax7.add_feature(cfeature.LAKES, alpha=0.5)# 以下6条语句是定义地理坐标标签格式f2_ax7.set_xticks(np.arange(leftlon, rightlon+10, 10),crs=ccrs.PlateCarree())f2_ax7.set_yticks(np.arange(lowerlat, upperlat+10, 10),crs=ccrs.PlateCarree())lon_formatter = LongitudeFormatter()lat_formatter = LatitudeFormatter()f2_ax7.xaxis.set_major_formatter(lon_formatter)f2_ax7.yaxis.set_major_formatter(lat_formatter)f2_ax7.set_title('Win', loc='left', fontsize=10)# 读取shp文件china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()# 绘制中国国界省界九段线等等f2_ax7.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)# 添加南海,实际上就是新建一个子图覆盖在之前子图的右下角f2_ax8 = fig2.add_axes([0.805, 0.053, 0.04, 0.07], projection=proj)f2_ax8.set_extent([105, 125, 0, 25], crs=ccrs.PlateCarree())f2_ax8.add_feature(cfeature.COASTLINE.with_scale('50m'))china = shpreader.Reader(r"D:\bou2_4l.dbf").geometries()f2_ax8.add_geometries(china, ccrs.PlateCarree(),facecolor='none', edgecolor='black', zorder=1)f7 = f2_ax7.scatter(lon4, lat4, s=2, c=pre4, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)f8 = f2_ax8.scatter(lon4, lat4, s=2, c=pre4, cmap='seismic',transform=ccrs.PlateCarree(), vmin=0, vmax=16)# colorbar 左 下 宽 高l = 0.88b = 0.06w = 0.015h = 0.5# 对应 l,b,w,h;设置colorbar位置;rect = [l, b, w, h]cbar_ax = fig2.add_axes(rect)cb = plt.colorbar(f4, cax=cbar_ax, extend='both')plt.savefig(r'D:\桌面\Seasonal Precipitation.png', dpi=300)plt.show()
绘制结果
3.一些参考和解释
1.为了方便,直接用了第一次画图的代码,然后因为太懒了,就没有用循环来写代码。(实际上是学艺不精)
2.与第一次画图的区别
为了给四幅图设置相同的colorbar,我在网上找了好多,但是都不是用plt.figure.add_axes方法画的图,就不适用于我这个图,只好在scatter中设置上下限。
关于为什么不用subplots等快捷的方法画这四幅图:因为图中还有南海子图,我没想明白怎么画子图套小图。。。
新增:对于colorbar添加了上下限(在scatter函数中,vmin和vmax)和尖角(在plt.colorbar中,extend=‘both’)
3.下面是在画图过程中搜索到觉得值得收藏的几篇文章
(13条消息) matplotlib contourf colorbar放到下方_Python空间绘图Colorbar详解_weixin_39790102的博客-CSDN博客
(14条消息) [Python3] Matplotlib —— (九) 多子图_TreasureAI的博客-CSDN博客
最全Python绘制多子图总结 - 知乎 ()
(14条消息) Matplotlib学习手册A005_Figure的add_axes()方法_Python草堂的博客-CSDN博客_add_axes
scatter函数参数(14条消息) Python中scatter函数参数详解_幸运六叶草的博客-CSDN博客_python scatter参数详解
4.不得不感慨官网yydsmatplotlib.axes.Axes.scatter — Matplotlib 3.5.2 documentation
5.希望时序图顺利(合十)