& q A& J r! Q7 L Notes:请务必将matplotlib的版本控制在3.2(或以下),经过测试发现,3.3及以后的版本在配合proplot使用时,在设置colorbar的时候会出现警告信息,同时生成的图不正常。降版本之后问题不再出现。 1 X+ `& V2 R) G: Y+ H/ ?! V0 z
在我的上一篇文章中,我推荐了由NCAR负责开发的PyNgl库作为Python语言下面的地理绘图库,并且介绍了如何在子系统(WSL)下面的安装方法。详细的请见传送门: 8 j! Z% O; {( g8 i9 T; k# J
% y0 x1 _, }) W# i; Q6 u. A% r 不过现在选择使用PyNgl有些尴尬,首先是官方宣布不再进行大更新了,只进行小修小补(维护模式),其次根据一些说法,PyNgl相较于NCL本身,还存在一些Bugs。总的来说就是体验一般。不过,如果很早就习惯了NCL的声明式绘图,可能你会非常喜欢他。 / Q9 R% H; J+ t. A2 P
一次偶然,我发现了Proplot这个库,Proplot对matplotlib进行了高度的封装,是一个高级绘图工具,其功能相当强大!而且融和了cartopy、basemap、xarray和pandas。作者是来自科罗拉多州立大学大气科学学院的硕士研究生Luke Davis。简单来说:Proplot针对matplotlib和cartopy的很多不友好的方面,并通过封装来解决这些问题。使用者可以通过新引入的format方法来完成繁琐复杂的图形设置问题(更简单的代码,更好看的图形) % x+ j2 l7 W! ]/ g! M2 U; I! P' `
& K$ c6 c( o1 s 在官方文档中,已经大量的绘图例子,可以前往查看,下面简单展示一下具体的绘图效果: * K. l4 p' i) q; ^9 B
①简单常用的填色图: 3 [+ c- z, R8 y3 @4 d, I2 D
import proplot as plot! e* a( s; C2 U9 c) J
import numpy as np
: a& S5 o6 A4 \( Q2 q' T
7 N5 S$ M, L' `% u$ Z # 创建虚拟数据# m: L2 D8 \- [" i+ s* @
offset = -40
7 S) ^$ k Z! Z% n lon = plot.arange(offset, 360 + offset - 1, 60)
" `1 j6 `4 J% Z* ~ lat = plot.arange(-60, 60 + 1, 30)* E0 G6 M6 P0 H8 m5 T
state = np.random.RandomState(51423)
" d% r/ A t* l2 N, _ data = state.rand(len(lat), len(lon))0 i! `! H( R$ l4 J( H( I( @8 q7 `* Q1 O
$ |# x- \2 K2 a: d% K plot.rc.reso = lo#海岸线可以不同分辨率 hi med lo x-hi xx-hi
% _6 X V8 |0 h! A6 {# v* m" R proj = plot.Proj(cyl)+ P1 m' ]& y; S2 B( g9 ~5 l$ B0 E# p
fig, axs = plot.subplots(nrows=1, ncols=2, axwidth=6, proj=proj)
$ y8 u1 Q% w% C/ f axs.format(6 x) W# K4 M/ O1 W9 h
abc=True,abcloc=ul,abcsize=30, abcstyle=a), gridlabelsize=18,
) r# w8 o' k; G8 r5 v+ F2 n labels=True, lonlines=30, latlines=20,
) q$ p" G8 M% V. s% k4 i6 Q. ` coast=True,gridminor=True,coastlinewidth=1,
+ }% m8 Q. X' T5 X' ~) I9 m$ x- W suptitle=Contourf,suptitlesize=20,
3 K( r& x1 _5 X5 w' e+ L6 e rowlabels=[Cartopy example],5 |+ s; m7 m- M; }# U' m- L
collabels=[Contourf, Pcolormesh])$ e- ~. i( r- O, K+ T7 l! q
cmap=plot.Colormap(Div, gamma=0.6)#gamma提高颜色深度* f( _7 f0 ~$ O5 g8 f( X
7 R( T( t8 Y( X( D# z% B; N m = axs[0].contourf(lon, lat, data, cmap=cmap, extend=both)
6 ~, S5 @8 Y! _$ A% j* `. f axs[1].pcolor(lon, lat, data, cmap=cmap, extend=both)
$ c# C( o0 E. V
( v9 r- [! c" r0 }6 }7 z fig.colorbar(m, loc=b, label=State,
3 l% R( v9 |, r L3 l9 h1 Y# \" O labelsize=20,ticklabelsize=18, extendsize=1.7em)5 x- ^' U: I4 a5 y4 D7 A7 A' R
fig.save(rC:\Users\59799\Desktop\image.png,0 j1 q, q/ K" F: g
dpi=600)
( b# |, o: c1 C% b2 c$ a plot.close()
" K8 D, r' x5 p* C# A 7 i- P8 E/ z. t8 `
: m/ h+ p$ k' w8 e8 m
②子图特殊布局: 0 W) h" l0 A9 I4 R5 {; X$ E5 r% x
import proplot as plot
2 t% p' i; g) g/ H, |' e; x% a d import numpy as np
& W8 H4 M5 t* N
7 ^% d3 y" n+ y( ^" ^ # 创建虚拟数据* [' V G. N! _' Y0 I% L! r. N
offset = -40
& U; v2 G) x4 |5 V" H lon = plot.arange(offset, 360 + offset - 1, 60)5 V9 @7 e$ x' }5 H9 \6 n9 M6 T3 a
lat = plot.arange(-60, 60 + 1, 30)
6 Z: L: r4 c# q, Y5 m state = np.random.RandomState(51423)
3 K$ a2 P! [3 {5 t data = state.rand(len(lat), len(lon)). X' ?! q2 W! f, x% F
. Y/ Q' ?* Q2 F" r# S9 ], Q& |: m: r, D
subplot_array = [[0,1,1,0],4 V" \: j8 i- H6 Y8 O: W2 F9 P8 D A) l& X
[2,2,3,3]] #0表示没有图片 1 2 3...表示子图1 2 3...
3 A- O# B* K& J. z' @" p; M! K* {& v$ u8 P& ~& J
plot.rc.reso = lo#海岸线可以不同分辨率 hi med lo x-hi xx-hi3 X$ N( x2 I1 v% \9 l* r0 @
proj = plot.Proj(cyl)4 l) V; Y( C- S7 _! A5 e4 X s
fig, axs = plot.subplots(subplot_array, axwidth=6, proj=proj)
1 ` l$ ?1 [( S1 |5 U1 [6 y axs.format() d3 C9 l; M$ X9 h
abc=True,abcloc=ul,abcsize=30, abcstyle=a), gridlabelsize=18,
! V- v" n' t- F; d: m0 ]2 ~ labels=True, lonlines=30, latlines=20,
0 a# N" j5 w3 j/ d; k coast=True,gridminor=True,coastlinewidth=1)% V7 Q, Z9 h# N7 S% o2 \5 Q3 ?" }* g0 z
cmap=plot.Colormap(Div, gamma=0.6)#gamma提高颜色深度
6 l ^ y& }8 g+ G. X0 I, d- }# Q
m = axs[0].contourf(lon, lat, data, cmap=cmap, extend=both)
; n, I2 A$ ?: X axs[0].format(title = subplot 1, titlesize=20)
+ \* p6 A* }" G) O$ {* I& ]
8 B; O5 q% `( n& R axs[1].pcolor(lon, lat, data, cmap=cmap, extend=both)8 m; k1 i3 s- R9 c3 n) ]" Q
axs[1].format(title = subplot 2, titlesize=20)' r# r9 r# g) ]! [
- x' a8 }0 J/ W1 i5 U
axs[2].contour(lon, lat, data, extend=both)
5 Q' \' p* Z2 a+ o0 }' i axs[2].format(title = subplot 2, titlesize=20)/ V7 u. O9 g0 M7 L' s: a2 z
. |5 Y9 u5 j' c- B1 H( E2 E) e fig.colorbar(m, loc=b, label=State,
( A3 T# L. ]: u7 Y labelsize=20,ticklabelsize=18, extendsize=1.7em)) n7 w6 S7 B$ V( [" d& x( ?* z
fig.save(rC:\Users\59799\Desktop\image.png,' U4 u+ k& J; _/ f# l9 ^; Q; l
dpi=600)
9 y1 ]2 l0 p0 _ plot.close() 5 R. ~9 k/ ~4 c5 t7 P) E- z
% h( A4 n' i ^ 使用技巧:
$ y0 k, X6 O5 t0 t) l: Z ①在保存图片时,默认保存的图片为1200dpi,如果直接放进word文档,可能会因为图片压缩导致图片异常(如果设置为不压缩,图片一多会导致word非常卡),所以请尽量使用dpi参数改变保存图片时候的dpi。
* r* v! j; Y0 w8 R ②format方法可以针对不同的子图设置不同格式,例如: " c6 o& |9 U5 @ \& _
axs.format(...)#设置全部子图4 k" V4 d- a5 a/ l4 M% a
axs[0:2].format(...)#设置第1张和第2张子图7 ~8 {- k3 L1 F0 g
axs[0].format(...)#设置第1张子图 1 B5 s$ ?* S2 ]! W
③所有的图形设置都可以在format方法中通过参数的方法完成,具体的参数请查阅官方文档的Configuring ProPlot章节
, K+ \# a* R0 z: c' x5 e# |8 } ④现在Proplot中还包含着basemap,个人不太推荐使用。 " D$ `+ A) ?. e
5 f0 u) i0 x a0 p1 @9 q
4 b7 P! j0 q6 o
! F+ T1 m8 {( J0 l
* m( T( `0 q* H |