# t. ?' j7 ~+ Q i& @* q
文章目录前言一、基础介绍二、区域地图的绘制总结前言+ J) g. M ` X: e4 g9 j) H0 U
常用地图底图的绘制一般由Basemap或者cartopy模块完成,由于Basemap库是基于python2开发的一个模块,目前已经不开发维护。故简单介绍cartopy模块的一些基础操作。
, U1 D" N; k/ M, i! s2 b1 ?
! n: C. x6 L: V4 _ 如果大家在学习中遇到困难,想找一个python学习交流环境,可以加入我们的python裙,关注小编,并私信“01”即可进裙,领取python学习资料,会节约很多时间,减少很多遇到的难题。 * A5 }6 m \7 `, B, J c
一、基础介绍" `; w0 A" r [5 S" P+ S" [
首先导入相关模块。 import numpy as np
) C3 A4 u$ O0 `; P0 w' w. } import matplotlib.pyplot as plt# z3 g* O2 Z& b3 D7 t7 ?, ]; F
import cartopy.crs as ccrs
0 \; G3 I4 n$ p2 T import cartopy.feature as cfeature7 A0 F s% `( X
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
f5 K, u2 \0 n# Y 12345
( ?* J$ m# I1 r. O1 x8 F 首先介绍参数projection,该命令可以配合ccrs设置投影类型,此处以方形投影命令为示例。其中central_longitude参数为投影中心位置。其中心设置与Basemap设置规则一样,详情可以看上一篇文章。 ax=plt.axes(projection=ccrs.PlateCarree(central_longitude=0))
# v. G8 F1 Q6 @0 a 1在设置好绘制类型后,绘制地图各特征量。其代码如下: #ax.add_feature(cfeature.LAKES.with_scale(scale))
+ R0 H5 Z: v2 b' W/ P1 H ax.add_feature(cfeature.OCEAN.with_scale(scale))' u% D; E, F g% v" h" x
#ax.add_feature(cfeature.RIVERS.with_scale(scale))
' m" j& i, ?: a7 o0 ^ #ax.add_feature(cfeature.LAND.with_scale(scale),lw=0.5)
. _* s9 p l: b ax.add_feature(cfeature.COASTLINE.with_scale(scale),lw=2)9 p6 |' J6 N. A$ E
123456 b: }5 n( \$ i7 u. E
参数scale为地图分辨率,目前支持10m,50m,110m,参数lw为线条粗细。此处绘制海岸线和海洋,效果图如下: - R2 Q% h1 m) y: B3 F" J
! m Y9 |; B7 s' R
5 B0 {$ [! z6 J, F/ d2 e# z 在绘制结束后,作为地图。经纬度自然是必不可少的,在该模块中,引进同时设置坐标轴标签改变该标签刻度的表示,具体形式如下: ax.set_xticks(np.arange(0,361,40), crs=ccrs.PlateCarree())
2 Y# K7 |' @0 U; t6 q0 k ax.set_yticks(np.arange(-90,90+30,30), crs=ccrs.PlateCarree())
7 Y+ s( Y, f, m ` #zero_direction_label用来设置经度的0度加不加E和W* i9 K! y8 r) X' r) T4 ?
lon_formatter = LongitudeFormatter(zero_direction_label=False)
4 g/ Z) G9 a; ?8 V. [ lat_formatter = LatitudeFormatter()" Q& H s" B. h" W7 |
ax.xaxis.set_major_formatter(lon_formatter)
0 |" f5 E, `( V2 A( C/ {- L ax.yaxis.set_major_formatter(lat_formatter)& R- u5 {- I9 G: g o8 y
1234567可以看到效果图如下: 5 j4 I% a4 k0 i5 j* V1 r
$ g# c- R/ o" X - l4 B" X4 A+ \8 L
当然如果想对坐标轴粗细变化可以引入一下命令。 ax.outline_patch.set_visible(False)/ l0 m) `& \* ]7 |0 k6 F
ax.spines[bottom].set_visible(True)
G7 R9 t% C" `" L6 s, f1 {0 y4 Y$ i ax.spines[left].set_visible(True)
$ Q; d! s k: e# m5 _% E ax.spines[right].set_visible(True)3 g/ a% j0 s5 a0 R( s
ax.spines[top].set_visible(True)
. p5 {, R/ ?; W2 |- _2 Q$ Y ax.spines[bottom].set_linewidth(2.5);###设置底部坐标轴的粗细& G1 I2 d" t5 @
ax.spines[left].set_linewidth(2.5);####设置左边坐标轴的粗细
: [# m2 L. O a, i% K ax.spines[right].set_linewidth(2.5);###设置右边坐标轴的粗细' l5 `) q7 ^1 _ l3 L
ax.spines[top].set_linewidth(2.5);####设置上部坐标轴的粗细
9 H* k7 E. a4 x- U: a' L- q% ~( J+ M0 y5 j+ C9 L
12345678910应该在该模块下,控制坐标轴的命令已经和常规不一样。因此先关闭该控制,然后开启常规坐标轴设置。
& a+ H4 H) Y( e4 D2 Y |% L 二、区域地图的绘制
/ c8 w! H: {) i) K5 f$ B 当我们在某一小块区域研究时,需要绘制区域地图。此时我们可以引入命令: ax.set_extent(box,crs=ccrs.PlateCarree())/ W/ J. z, D* v- n+ `: H9 K5 _
1
/ Q1 k6 n# \8 b1 | 其中box为绘制区域,crs为投影类型。其他命令基本不变。设置box为[40,180,0,90],可得到效果图如下:
5 n" s" |5 I- l5 s7 P% f6 t* ]
& P# p) z) h. P- P : X! X/ S/ a9 v( `
总结5 j; [+ N, N# R7 I. L5 \# Y
为方便各位读者,我书写了绘制地图的函数,大家在使用时可直接调用。此处示例为方形投影,若希望绘制其他投影。只需要修改函数部分参数即可。代码如下: def map_make(scale,box,xstep,ystep):1 l1 ]: V) V. e4 t/ [# y
ax=plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
" Y `7 p+ ^: O a = (box[1]-box[0])//xstep: C5 f: y- Z# j
x_start = box[1] - a*xstep
6 ^; B1 X) `; v" M* o a = (box[3]-box[2])//ystep
3 Z. t( ?2 x9 B' {. r y_start = box[3] - a*ystep
3 J5 i$ w/ P [) e( q0 n( Q ax.set_extent(box,crs=ccrs.PlateCarree())
\: c2 j5 U& a; S* r$ h9 C #ax.add_feature(cfeature.LAKES.with_scale(scale))- `6 I Y/ V4 W9 t# U
#ax.add_feature(cfeature.OCEAN.with_scale(scale))
# F) Q6 M- v: ]3 f6 k- b0 k* H #ax.add_feature(cfeature.RIVERS.with_scale(scale))
! n3 {- E; Q4 n6 q5 z3 ]; J #ax.add_feature(cfeature.LAND.with_scale(scale),lw=0.5)
- n+ S8 P+ `" T0 g' N% u ax.add_feature(cfeature.COASTLINE.with_scale(scale),lw=2); s; Q- m3 ^4 Z. ?3 l' C% n* l# T, z* R
0 J' Q6 z3 r( x( y! C ax.set_xticks(np.arange(x_start,box[1]+xstep,xstep), crs=ccrs.PlateCarree()) x7 \: S1 p t6 `
ax.set_yticks(np.arange(y_start,box[3]+ystep,ystep), crs=ccrs.PlateCarree())
C o: Y3 t% O. G6 [ #zero_direction_label用来设置经度的0度加不加E和W2 P% }; q% k V: E
lon_formatter = LongitudeFormatter(zero_direction_label=False)
+ C; A& U& v& [9 G" x9 z8 E7 p lat_formatter = LatitudeFormatter()2 J& a4 h) l+ v+ ~" G5 k8 U
ax.xaxis.set_major_formatter(lon_formatter)
$ U, j% q+ y) N3 L ax.yaxis.set_major_formatter(lat_formatter)
: ~0 u6 R. S- P6 P& r1 k. a #添加网格线6 J4 B* M: I6 T2 o
ax.grid()/ A; J/ t( {; G3 k( h
$ X9 s/ g m8 ]' u, m, v
ax.outline_patch.set_visible(False)
% X# E& {% Z' ?4 s ax.spines[bottom].set_visible(True)3 |. J: ]" ~# F, j4 G' }: L/ l- ]
ax.spines[left].set_visible(True)/ t* ~% ~5 h9 a, X
ax.spines[right].set_visible(True)
3 E. ~; ]5 L1 B' v' O7 c1 H1 { ax.spines[top].set_visible(True)
7 v: N" U, C" S, b! s ax.spines[bottom].set_linewidth(2.5);###设置底部坐标轴的粗细1 L; K- i2 j! X8 w( a! \
ax.spines[left].set_linewidth(2.5);####设置左边坐标轴的粗细
0 \) w* J" M2 T9 x! k ax.spines[right].set_linewidth(2.5);###设置右边坐标轴的粗细
! m |! P; x! d ax.spines[top].set_linewidth(2.5);####设置上部坐标轴的粗细) [* ?6 W# x+ _5 W6 j) ^
7 W0 q, T3 z) G* z. j
return ax最后多说一句,想学习Python可联系阿喵,这里有我自己整理的整套python学习资料和路线,想要这些资料的都可以关注阿喵,并私信“01”领取。 - S$ W$ @) _ }) v6 e
+ Z( I, E4 T: r! T* r( Q
/ ^" m K4 S7 F9 \- ~: a2 Z( o8 ~/ q1 R3 Q2 u7 B. P
. @* R! t7 | j. e& l' ?) Q6 Y |