初学matplotlib小结

瞎哔哔

前言

本人不幸从龙王山皇家气象学院毕业后,又继续投入了祖国气象事业怀抱。为了肩负国家崛起的重任(?),不得不苦学python,其过程之痛苦按下不表。

于今日开学之际简单做一些暑假所学之小结,谨以此回望那个笨拙、不知道怎么获取知识、一学习编程语言就想昏倒的,当初的自己。

冀以尘雾之微补益山海,荧烛末光增辉日月。

(补:我偶像目前是杨效业学长(大气院的优秀学长之一(某站id是摸鱼的那位)

(万一十年后我还在从事气象相关事业,看到这篇博客会不会被自己的中二之魂震惊到)

简介

matplotlib,就是我们『Linux与python,后面记不住了』那门课的第四章,主要是一个用于气象类画图的库。官网链接:https://matplotlib.org/stable/plot_types/basic/index.html

切记

实操中有什么不会的,直接

help(#里面是不会的、想要查询的内容#)

大部分时间都可以获得想要的解答。有的可能不能直接写进括号,尝试一下定义ax后,help(ax.想要查询的)。我在这篇中默认你通过了英语六级,看得懂基础英文释义。(虽然两者没有直接关联)

然后就认真开始写了!

最后强调一下,代码给出的只是局部,读者可自行根据上下文补全

(主要是省略了安装库、创建画布、投影等等)

画布

创建画布

import matplotlib.pyplot as plt

先把库安装上,才可以用。 

fig=plt.figure(dpi=200)

dpi是清晰度,200就够用了。创建出来的fig就是画布的名字。然后在画布里添加子图。

ax1=fig.add_axes([0.1, 0.1, 1.2,1.0])

前两个表示起始位置,后两个表示子图的长和宽。

ax = plt.subplot(1, 1, 1)

这是另一种创建子图的方法,但是我不太会用。

地图投影

你要画地形图的话,就需要用到地图投影,对应的代码应该长成这样:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs

ax1=fig.add_axes([0.1, 0.1, 1.2,1.0],projection=ccrs.PlateCarree())
from cartopy.io.shapereader import Reader

SHP=r'#shp存放路径#\map'
ax1.add_geometries(Reader(os.path.join(SHP, 'China.shp')).geometries(),ccrs.PlateCarree(), facecolor='none', edgecolor='grey', linewidth=1.5)

上为叠加国界线(国界线、省界线等应为shp文件)

ax1.coastlines(lw=1.5)

上为叠加海岸线。同理可添加陆地、海洋、河流。但是不好说,我印象里时灵时不灵的。

至于白化?我也不会。

画图

我感觉我写的磨磨唧唧的,要加快速度了。

网格线

不建议添加,因为我每次加了都被导师说画图不美观而删除。

ax.grid(True, linestyle='-', linewidth=0.3, color='gray',alpha=0.5)

直线

ax.plot(year,t,label='temperature',alpha=0.5,c='black',lw=2)

第一个地方写x轴,第二个地方写y的大小。两者不匹配会报错。

x轴接在一起

我想要两段x轴接在一起怎么办?比如x轴是20-30年,但是我有一组x=20-25的y和一组x=26-30的y

直接写进去就好了。

ax2.bar(year[0:14],delta_t[0:14],label='delta', linewidth=2,color='MediumSlateBlue',alpha=0.6)
ax2.bar(year[14:23],delta_t[14:23],label='delta', linewidth=2,color='MediumTurquoise',alpha=0.5)

(我不想放运行不成功的代码,在这段里,bar表示柱状图,其他与plot一样)

地图投影画方框(透明)

已经是地图投影了,就直接经纬度,然后四条直线画出方框

ax1.plot([1992.5,2001.4],[0.7,0.7],linestyle='-', color='b', linewidth=2.5)
ax1.plot([1992.5,2001.4],[-4.2,-4.2],linestyle='-', color='b', linewidth=2.5)
ax1.plot([1992.5,1992.5],[0.7,-4.2],linestyle='-', color='b', linewidth=2.5)
ax1.plot([2001.4,2001.4],[0.7,-4.2],linestyle='-', color='b', linewidth=2.5)

图例及其相关

ax1.legend(fontsize=18, frameon=False,loc=7)

条形图/柱状图

刚刚举了一个例子,再来一个:

ax2.bar(year,delta_t,label='delta', linewidth=2, color='MediumSlateBlue',alpha=0.6)

柱状图显示数值:

原文链接:https://blog.csdn.net/qq_35240689/article/details/126743893?spm=1001.2014.3001.5506

for bar in bars:
    height = bar.get_height()
    ax.annotate(f'{height+100:.1f}', xy=(bar.get_x() + bar.get_width() / 2, height),
                fontsize=14, color='black',
                xytext=(0, 4), textcoords='offset points', ha='center', va='bottom')
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。                        
原文链接:https://blog.csdn.net/qq_35240689/article/details/126743893

我自己也仿照写过:

baro=ax1.bar(np.arange(29)+0.05,pr3[1:],lw=0.6,color='k',label='Observation',width=0.3,alpha=0.7)

for bar in baro:
    height = bar.get_height()
    if height>=50:
        ax1.annotate(f'{height:.1f}', xy=(bar.get_x() + bar.get_width() / 2, height),
                fontsize=14, color='black',
                xytext=(0, 4), textcoords='offset points', ha='center', va='bottom')

如果后面要接着调用,要给ax.bar命名。(示例中我命名为了baro)

柱状图对齐

barc=ax1.bar(np.arange(29)+0.35,cpr3[1:],lw=0.6,color='b',label='ctrl-rail',width=0.3,alpha=0.7)
bars=ax1.bar(np.arange(29)+0.65,spr3[1:],lw=0.6,color='r',label='sens-rail',width=0.3,alpha=0.7)

help(ax.bar)之后你可以查看,他是可以规定从调节align参数调节的,但是实际效果并不好。

我当时好像是想把barc的左半边和x轴0刻度线对齐,使用align参数、设置x轴对应的位置(np.arange(29)+0.35)均不能达到目的。最后是通过移动y轴相对位置达成了目的。

等值线填色图

噩梦起源。

cf=ax.contourf(x,y,t,transform=ccrs.PlateCarree(),cmap='Spectral_r',extend='max',
               levels=np.arange(0,40,4),linewidths=0.8)

contourf是区域填色,contour是等值线填色,虽然我严重认可后者的颜值,但是前者更深得民心,日常应用也多为前者。

x和y就是一维数组,lat和lon,t是二维数组,两个维度形状应该分别和xy一致。transform就是投影方式。cmap是使用的颜色。

matplotlib自带颜色的链接:

https://blog.csdn.net/qq_43201025/article/details/131043840?spm=1001.2014.3001.5506

颜色自设定

然而实际应用中我们大多是自己写颜色条,我觉得导师不懂内置颜色的审美。双色条真的很好看啊。等值线图countourf颜色设定如下:

from matplotlib.cm import get_cmap
from matplotlib import cm, colors, ticker

proj = ccrs.PlateCarree()
colorlist = ['#000080','#4169E1','#6495ED','#87CEFA','#B0E0E6','#E1FFFF','#FFFACD','#FFD700','#FFA500','#FF7F50','#FF0000','#B22222']
# colorlist = ['海军蓝','皇军蓝','矢车菊','淡蓝色','火药蓝','淡青色','柠檬薄纱','金','橙色','珊瑚','纯红','耐火砖']

cf = ax1.contourf(lon, lat, t, colors=colorlist,transform=proj,extend='both')

colorbar

colorbar就是contourf的颜色条。我主要用到的是为colorbar设置位置。

cf1 = ax1.contourf(lonc, latc, mfdc, colors=colorlist3,levels=bounds2, transform=proj,extend='both')
axcb1=fig.add_axes([0.2,1.77,1.0,0.03])
cb1=plt.colorbar(cf1,fraction=0.05, pad=0.15,drawedges=True,orientation='horizontal',cax=axcb1)  

axcb就是你可以设置colorbar的位置。

风场

风羽图

用的很少,对应的函数是ax.barb

箭头图

用的很多。我印象里基本上我画个矢量就是用它。风场也是一样。

cq=ax1.quiver(lon,lat,u,v,transform=ccrs.PlateCarree(),width=wid,scale=sca*1.5,color='black')

命名cq之后,矢量箭头可以不跟他画在同一张图上。比如我导的要求是在图内部的右下角添加空白条,然后画箭头。(添加空白图形/添加空白长方形)我的处理方法是添加了ax2后把quiverkey画在ax2上,再把ax2的坐标轴删除,即得到空白长方形。

key=ax2.quiverkey(cq,quiverleft,quiverright,quiverwind,label=quiverlabel,labelpos='E', coordinates='data')

注意这里的覆盖顺序,ax2优先覆盖在ax1上,如果在ax1上画quiverkey,就看不见。

我是不是越写越抽象了,我怀疑初学者看到这里可能有点懵圈。别急,你去看看我偶像,id摸鱼今天在摸鱼吗,在隔壁某站的教学视频,你就明白了。

流线图

画法和箭头图一样的,就是最后显示的结果是流线。ax.streamplot,我画过几次,因为我看不出辐合辐散,需要借助流线图。但是我导他们就纯看箭头图就明白了。嗯,所以说,这东西可能只对初学者有用吧。

文字

ax1.text(0.02, 0.9, "helloworld", fontsize=28, transform=ax1.transAxes, fontweight="bold")

文字设置上标

words=fig.text(0.53,1.57,s='10$^-$$^5$ kg/m$^2$·s',fontdict=None,fontsize=25)

$^2$就可以达成目的了。但是这个方法的劣势是一次只能修改一个上标字符。

更多方法参考:https://blog.csdn.net/qq_57313910/article/details/132699247?spm=1001.2014.3001.5506

坐标轴

这段代码是我从师兄那边抄过来的。大意为设置画图时的基础字体和大小。遇到很难找到代码的(比如说quiverkey的字体大小)这类的设置,就可以直接改动这一部分。节省很多事。

plt.rcParams['font.weight'] = 'bold'
plt.rcParams['font.family'] = 'Times New Roman' 
plt.rcParams['font.size'] = 25

内容较多,可通过小标题查询

隐藏坐标轴

ax2.get_xaxis().set_visible(False) # 隐藏x坐标轴
ax2.get_yaxis().set_visible(False) # 隐藏y坐标轴

隐藏边界线

ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)

我还看到可以设置坐标轴的宽度为0的方法,理论上也应该可以达成目的。

设置坐标轴粗细

ax1.spines['bottom'].set_linewidth(2)  ###设置底部坐标轴的粗细
ax1.spines['left'].set_linewidth(2)  ####设置左边坐标轴的粗细

地图投影

很不负责地说,每次地图投影的坐标轴我都是以下这段代码整段搬上去的。他们好像功能重复了又好像没重复。

import matplotlib.pyplot as plt
import cartopy.mpl.ticker as cticker
import cartopy.feature as cfeat
import cartopy.crs as ccrs

lat_formatter=cticker.LatitudeFormatter()
lon_formatter=cticker.LongitudeFormatter()
ax1.xaxis.set_major_formatter(lon_formatter)
ax1.yaxis.set_major_formatter(lat_formatter)
ax1.set_xticks(np.arange(leftlon,rightlon+0.1,5),crs=ccrs.PlateCarree())
ax1.set_yticks(np.arange(lowerlat,upperlat+0.1,2),crs=ccrs.PlateCarree())

后面两个是设置坐标间距。

 设置地图投影的范围

leftlon,rightlon,lowerlat,upperlat=( 70 , 110 , 20 , 45 )
img_extent=[leftlon,rightlon,lowerlat,upperlat]
ax3.set_extent(img_extent)

 设置x轴y轴轴题

plt.xlabel("",fontsize=28, fontname="Times New Roman") #fontweight="bold"
plt.ylabel("",fontsize=28, fontname="Times New Roman") #fontweight="bold"

自定义x轴/y轴

point = []
print(len(rain))
for i in range(0, len(rain), 24):
        iday = int(day + (hour + i) / 24)
        ihour = (hour + i) % 24
        point.append('%02d' % (iday))
ax.set_xlim(0, len(rain) - 1)
ax.set_xticks(range(0, len(rain), 24))
ax.set_xticklabels(point, fontsize=35, rotation=0, fontname="Times New Roman",fontweight="bold")

这段代码的意思呢,就是我写了个列表,然后大概是x月x日,这样,来命名x轴。

重点将我的列表设置成x轴的那个参数是『ax.set_xticklabels』。y轴只需要x改成y。

修改x轴/y轴字体、大小

ax.set_xlabel("date", fontsize=45, fontname="Times New Roman", labelpad=20., fontweight="bold")
ax.set_ylabel('precipitation(mm)', fontsize=45, fontname="Times New Roman",labelpad=30.,fontweight="bold")

设置x轴、y轴刻度与轴字的间距

ax.tick_params(axis='x', width=2, colors='k', length=12, pad=9)
ax.tick_params(axis='y', width=2, colors='k', length=12, pad=9)

脆皮女大困了,,,加油,,,

设置x轴,y轴位置

就是零刻线位置,使他们对齐。我语言表述系统开始bug了。

ax1.spines['left'].set_position(('data',-2)) 
ax1.spines['top'].set_position(('data',600)) 

这是给了我类似帮助的一篇干货:https://blog.csdn.net/houston12138/article/details/136403329?spm=1001.2014.3001.5506

看到这里辛苦你了也辛苦我了

不知不觉我竟然已经倾囊尽授(好吧,不是这样用的)已经江郎才尽了,加油,我们的路都很长,这里是我一小段旅途的歇脚之处,也是未来的路继续向前的信心来源(写这么长的干货给我提供的情绪价值真的很饱满好吧)祝读者和我都能一帆风顺,前途似锦。

ps. 第一次用,不知道博客可不可以修改,后面如果有补充我尽量更新到这篇上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值