前言 + ?: h2 m: E* @& [( Y
海洋、气象、地球科学相关的分析必然少不了地图的可视化。Python中我常用的绘制地图和空间信息分析的库是Cartopy。 Cartopy有一个非常严重的问题,那就是自带的中国国界数据有问题,这也是很多国外开源库的普遍问题。在做中国区域的分析时,由于九段线的位置很偏南,因此最标准的做法是同时绘制南海区域的子图。在做一些站点展示的时候,如果只单独画上几个站点总觉得很丑,可以加上一些地形背景。 综上,今天想要用一个小例子解决这3个问题: 正确的中国国界线及九段线绘制 南海小地图绘制 全球地形图添加
# K+ w! _ V4 R+ R 准备工作获取正确的中国矢量文件:公众号后台留言“中国行政区划”
, ^0 I6 J; J3 W3 c0 S2 a(这个矢量文件来自资源环境平台,并和权威机构的标准地图做了比对,吻合一致。) 获取全球地形图像:公众号后台留言“全球地形”* s4 _. [" ]/ v! v6 o7 g
(提供的是全球50m分辨率的tif图,如果对分辨率要求不高可以直接使用stock_img()) & G" U, _ T, l+ g! K: H
代码[Python] 纯文本查看 复制代码 # -*- coding: utf-8 -*-
importnumpy asnp
importpandas aspd
importcartopy
importcartopy.crs asccrs
importcartopy.feature ascfeat
fromcartopy.mpl.gridliner importLONGITUDE_FORMATTER, LATITUDE_FORMATTER
fromcartopy.io.shapereader importReader, natural_earth
importmatplotlib.pyplot asplt
importmatplotlib.ticker asmticker
frommatplotlib.image importimread
defcreate_map():
shp_path = './cn_shp/Province_9/'
# --创建画图空间
proj = ccrs.PlateCarree() # 创建坐标系
fig = plt.figure(figsize=(6, 8), dpi=400) # 创建页面
ax = fig.subplots(1, 1, subplot_kw={'projection': proj})
# --设置地图属性
provinces = cfeat.ShapelyFeature(
Reader(shp_path + 'Province_9.shp').geometries(),
proj, edgecolor='k',
facecolor='none'
)
# 加载省界线
ax.add_feature(provinces, linewidth=0.6, zorder=2)
# 加载分辨率为50的海岸线
ax.add_feature(cfeat.COASTLINE.with_scale('50m'), linewidth=0.6, zorder=10)
# 加载分辨率为50的河流~
ax.add_feature(cfeat.RIVERS.with_scale('50m'), zorder=10)
# 加载分辨率为50的湖泊
ax.add_feature(cfeat.LAKES.with_scale('50m'), zorder=10)
ax.set_extent([105, 133, 15, 45])
# ax.stock_img()
ax.imshow(
imread('./NE1_50M_SR_W.tif'),
origin='upper',
transform=proj,
extent=[-180, 180, -90, 90]
)
# --设置网格点属性
gl = ax.gridlines(
crs=ccrs.PlateCarree(),
draw_labels=True,
linewidth=1.2,
color='k',
alpha=0.5,
linestyle='--'
)
gl.xlabels_top = False# 关闭顶端的经纬度标签
gl.ylabels_right = False# 关闭右侧的经纬度标签
gl.xformatter = LONGITUDE_FORMATTER # x轴设为经度的格式
gl.yformatter = LATITUDE_FORMATTER # y轴设为纬度的格式
gl.xlocator = mticker.FixedLocator(np.arange(95, 145+ 5, 5))
gl.ylocator = mticker.FixedLocator(np.arange(-5, 45+ 5, 5))
# --设置小地图
left, bottom, width, height = 0.67, 0.15, 0.23, 0.27
ax2 = fig.add_axes(
[left, bottom, width, height],
projection=proj
)
ax2.add_feature(provinces, linewidth=0.6, zorder=2)
ax2.add_feature(cfeat.COASTLINE.with_scale('50m'), linewidth=0.6, zorder=10)
ax2.add_feature(cfeat.RIVERS.with_scale('50m'), zorder=10)
ax2.add_feature(cfeat.LAKES.with_scale('50m'), zorder=10)
ax2.set_extent([105, 125, 0, 25])
# ax2.stock_img()
ax2.imshow(
imread('./NE1_50M_SR_W.tif'),
origin='upper',
transform=proj,
extent=[-180, 180, -90, 90]
)
returnax
defmain():
ax = create_map()
title = f'distribution of station around China'
ax.set_title(title, fontsize=18)
df = pd.read_csv('buyo_position.csv')
df['lon'] = df['lon'].astype(np.float64)
df['lat'] = df['lat'].astype(np.float64)
ax.scatter(
df['lon'].values,
df['lat'].values,
marker='o',
s=10,
color ="blue"
)
fori, j, k inlist(zip(df['lon'].values, df['lat'].values, df['name'].values)):
ax.text(i - 0.8, j + 0.2, k, fontsize=6)
plt.savefig('station_distribute_map.png')
if__name__ == '__main__':
main()
[p=null, 2, center]
资源获取地址:
# q/ x- T4 ^1 [/ b2 e! ]8 p+ u2 l $ c3 |' R$ s+ N# B9 a: R% C! t7 ^, o
. \; }: |# d1 I/ p% a% s( O3 G& @0 B) X
|