首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >常见地图白化方法(一)

常见地图白化方法(一)

作者头像
用户11172986
发布于 2024-06-20 17:44:57
发布于 2024-06-20 17:44:57
6750
举报
文章被收录于专栏:气python风雨气python风雨

前言

地图白化是一种绘制地图的技术,它可以实现对感兴趣区域以外的数据进行遮盖或填充白色的效果,从而突出显示目标区域的特征。 地图白化的原理是利用 shapefile 文件中的多边形坐标来创建一个剪切路径,然后将这个路径应用到 matplotlib 的绘图对象上,使得只有路径内的数据可见,路径外的数据被隐藏或覆盖。 气象家园的五星上将兰溪之水说过,其实所谓的“白化”一般就两种途径:①mask数据;②mask图形

方法一 set_clip_path方法

matplotlib 官方函数示例

代码语言:javascript
复制
代码语言:javascript
复制
import numpy as np 
import matplotlib.cm as cm 
import matplotlib.pyplot as plt 
from matplotlib.path import Path 
from matplotlib.patches import PathPatch  
delta = 0.025
x = y = np.arange(-3.0, 3.0, delta) 
X, Y = np.meshgrid(x, y) 
  
Z1 = np.exp(-X**2 - Y**2) 
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2) 
Z = (Z1 - Z2) * 2
   
path = Path([[0, 1], [1, 0], [0, -1], 
            [-1, 0], [0, 1]]) 
patch = PathPatch(path, facecolor ='none') 
   
fig, ax = plt.subplots() 
ax.add_patch(patch) 
   
im = ax.imshow(Z, 
               interpolation ='bilinear',  
               cmap = cm.gray, 
               origin ='lower',  
               extent =[-3, 3, -3, 3], 
               clip_path = patch,  
               clip_on = True) 
  
im.set_clip_path(patch) 
  
fig.suptitle('matplotlib.axes.Axes.set_clip_path()function Example\n\n', fontweight ="bold") 
  
plt.show() 

代码的目的是生成一个二维网格图,并在其中添加一个路径(path)作为剪裁(clip)区域,只显示路径内部的部分。 原图如下

代码语言:javascript
复制
代码语言:javascript
复制
fig, ax = plt.subplots() 
ax.imshow(Z, 
    interpolation ='bilinear',  
    cmap = cm.gray, 
     origin ='lower',  
    extent =[-3, 3, -3, 3]) 
plt.show() 

属于mask图片类型

代码语言:javascript
复制
读取era5数据
import xarray as xr
nc = xr.open_dataset('/home/mw/input/1107125177/2023110720.nc')

数据处理
data= nc.z[0,2,:,:]
lon=data.longitude
lat=data.latitude

导入库与生成路径
import cartopy.io.shapereader as shpreader
from cartopy.mpl.patch import geos_to_path
import matplotlib.pyplot as plt
from matplotlib.path import Path
import cartopy.crs as ccrs
import cmaps
# 读取shp文件
shp_path = '/home/mw/input/china1656/china_map/china_map/China_Province_2022.shp'
shp = shpreader.Reader(shp_path)
geo_list = list(shp.geometries())
proj = ccrs.PlateCarree()
poly = geo_list[17]
path = Path.make_compound_path(*geos_to_path(poly))

绘图部分
In [16]:
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(projection=ccrs.PlateCarree())

cf = ax.contourf(lon, lat, data/98 ,levels=np.arange(520,600,4),transform=proj, cmap=cmaps.radar)
cr = ax.contour(lon,lat, data/98, colors='k',levels=np.arange(520,600,4))
ax.clabel(cr, inline=1, fontsize=10, fmt="%i")
ax.add_geometries(shp.geometries(), proj, facecolor='none', edgecolor='k') 
ax.set_extent([100,120,20,40])

# 白化中国以外的区域
for col in cf.collections:
    col.set_clip_path(path, transform=ax.transData)
# 色标 
cb = plt.colorbar(cf, orientation='vertical', shrink=0.8)
plt.show()

这时候有不懂事的小朋友要问了,你这geo_list是什么,根本看不懂 哎呀,别急,马上给你print出来

代码语言:javascript
复制
代码语言:javascript
复制
geo_list[17]
代码语言:javascript
复制

你问我为什么知道广东省的序号是17,那当然是用geopandas看的

代码语言:javascript
复制
代码语言:javascript
复制
shp = gpd.read_file("/home/mw/input/china1656/china_map/china_map/China_Province_2022.shp")
shp
代码语言:javascript
复制

省

省级码

省类型

ENG_NAME

VAR_NAME

FIRST_GID

FIRST_TYPE

year

geometry

0

北京市

110000

直辖市

Beijing

Běi Jīng

110000

Municipality

2022

POLYGON ((117.38335 40.22647, 117.38557 40.224...

1

天津市

120000

直辖市

Tianjin

Tiān Jīn

120000

Municipality

2022

POLYGON ((117.56937 40.19153, 117.56744 40.189...

2

河北省

130000

省

Hebei

Hé Běi

130000

Province

2022

MULTIPOLYGON (((118.26945 38.98097, 118.26871 ...

3

山西省

140000

省

Shanxi

Shān Xī

140000

Province

2022

POLYGON ((114.13714 40.73445, 114.13860 40.732...

4

内蒙古自治区

150000

自治区

Neimenggu

Nèi Měng Gǔ

150000

Autonomous Region

2022

POLYGON ((121.49813 53.32607, 121.50116 53.321...

5

辽宁省

210000

省

Liaoning

Liáo Níng

210000

Province

2022

MULTIPOLYGON (((121.03521 38.87021, 121.03528 ...

6

吉林省

220000

省

Jilin

Jí Lín

220000

Province

2022

POLYGON ((123.90309 46.29744, 123.90283 46.294...

7

黑龙江省

230000

省

Heilongjiang

Hēi Lóng Jiāng

230000

Province

2022

POLYGON ((123.40249 53.53506, 123.40471 53.535...

8

上海市

310000

直辖市

Shanghai

Shàng Hǎi

310000

Municipality

2022

MULTIPOLYGON (((121.87476 31.63516, 121.87542 ...

9

浙江省

330000

省

Zhejiang

Zhè Jiāng

330000

Province

2022

MULTIPOLYGON (((120.47933 27.15321, 120.48163 ...

10

安徽省

340000

省

Anhui

ān Huī

340000

Province

2022

POLYGON ((116.42485 34.65234, 116.43225 34.642...

11

福建省

350000

省

Fujian

Fú Jiàn

350000

Province

2022

MULTIPOLYGON (((117.29228 23.59563, 117.29206 ...

12

江西省

360000

省

Jiangxi

Jiāng Xī

360000

Province

2022

POLYGON ((116.68416 30.07160, 116.68576 30.070...

13

山东省

370000

省

Shandong

Shān Dōng

370000

Province

2022

MULTIPOLYGON (((119.92414 35.62384, 119.92294 ...

14

河南省

410000

省

Henan

Hé Nán

410000

Province

2022

MULTIPOLYGON (((111.02770 33.17911, 111.02767 ...

15

湖北省

420000

省

Hubei

Hú Běi

420000

Province

2022

MULTIPOLYGON (((113.12740 29.43223, 113.11645 ...

16

湖南省

430000

省

Hunan

Hú Nán

430000

Province

2022

MULTIPOLYGON (((109.47771 26.84005, 109.47793 ...

17

广东省

440000

省

Guangdong

Guǎng Dōng

440000

Province

2022

MULTIPOLYGON (((110.59023 20.37852, 110.59232 ...

18

广西壮族自治区

450000

自治区

Guangxi

Guǎng Xī

450000

Autonomous Region

2022

MULTIPOLYGON (((109.20674 20.91898, 109.20686 ...

19

海南省

460000

省

Hainan

Hǎi Nán

460000

Province

2022

MULTIPOLYGON (((112.04381 3.83812, 112.01370 3...

20

重庆市

500000

直辖市

Chongqing

Chóng Qìng

500000

Municipality

2022

POLYGON ((109.57960 31.72849, 109.58644 31.725...

21

四川省

510000

省

Sichuan

Sì Chuān

510000

Province

2022

POLYGON ((102.95840 34.27996, 102.95933 34.270...

22

贵州省

520000

省

Guizhou

Guì Zhōu

520000

Province

2022

MULTIPOLYGON (((105.09467 24.92520, 105.09458 ...

23

云南省

530000

省

Yunnan

Yún Nán

530000

Province

2022

POLYGON ((99.11276 29.21149, 99.11737 29.20723...

24

西藏自治区

540000

自治区

Xizang

Xī Zàng

540000

Autonomous Region

2022

POLYGON ((88.38821 36.47854, 88.38945 36.47845...

25

陕西省

610000

省

Shaanxi

Shǎn Xī

610000

Province

2022

POLYGON ((108.13454 36.57919, 108.13418 36.580...

26

甘肃省

620000

省

Gansu

Gān Sù

620000

Province

2022

POLYGON ((97.19051 42.76287, 97.23601 42.67222...

27

青海省

630000

省

Qinghai

Qīng Hǎi

630000

Province

2022

POLYGON ((100.91694 38.17344, 100.91780 38.173...

28

宁夏回族自治区

640000

自治区

Ningxia

Níng Xià Huí Zú

640000

Autonomous Region

2022

MULTIPOLYGON (((106.06218 35.43728, 106.06239 ...

29

新疆维吾尔自治区

650000

自治区

Xinjiang

Xīn Jiāng

650000

Autonomous Region

2022

POLYGON ((87.79720 49.18060, 87.81916 49.17268...

30

台湾省

710000

省

Taiwan

Tái Wān

710000

Province

2022

MULTIPOLYGON (((123.69793 25.92930, 123.69726 ...

31

香港特别行政区

810000

特别行政区

HongKong

Hong Kong

810000

Special District

2022

MULTIPOLYGON (((114.22665 22.54375, 114.22661 ...

32

澳门特别行政区

820000

特别行政区

Aomen

ào Mén

820000

Special District

2022

MULTIPOLYGON (((113.55346 22.21547, 113.55374 ...

33

江苏省

320000

省

Jiangsu

Jiāng Sū

320000

Province

2022

MULTIPOLYGON (((121.56617 32.22928, 121.56693 ...

这时这个方法就显示出弊端,读者的shp千变万化,没安装geopandas又对自己的shp列表不熟,则要一一排查geolist

方法二 rioxarray的rio.clip

代码语言:javascript
复制
代码语言:javascript
复制
代码语言:javascript
复制
import os
import numpy as np
import geopandas as gpd
import rioxarray
import xarray as xr
from shapely.geometry import mapping
import matplotlib.pyplot as plt

# 读取中国省份地图数据
shp = shpreader.Reader(shp_path)
shpgpd = gpd.read_file(shp_path)

# 设置数据投影
data.rio.write_crs("epsg:4326", inplace=True)

# 进行裁剪并绘图
cliped = data.rio.clip(shpgpd.geometry.apply(mapping), shpgpd.crs, drop=False)

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(projection=ccrs.PlateCarree())
cf = ax.contourf(lon, lat, cliped/98,levels=np.arange(520,600,4), transform=proj, cmap=cmaps.radar)
cr = ax.contour(lon,lat, cliped/98,levels=np.arange(520,600,4), colors='k')
ax.clabel(cr, inline=1, fontsize=10, fmt="%i")
ax.add_geometries(shp.geometries(), proj, facecolor='none', edgecolor='k') 
ax.set_extent([100,120,20,40])
cb = plt.colorbar(cf, orientation='vertical', shrink=0.8)
plt.show()
代码语言:javascript
复制
代码语言:javascript
复制

以上就是比较典型的mask数据类,此类锯齿较明显

拓展:一个省怎么画:使用裁剪后的行政区json进行绘图

代码语言:javascript
复制
代码语言:javascript
复制
gd = shpgpd[shpgpd['省'] == '广东省']
gd.to_file('/home/mw/project/gd.geojson', driver='GeoJSON')



# 读取中国省份地图数据
js_path = '/home/mw/project/gd.geojson'
gpdjs = gpd.read_file(js_path)

# 设置数据投影
data.rio.write_crs("epsg:4326", inplace=True)

# 进行裁剪并绘图
cliped = data.rio.clip(gpdjs.geometry.apply(mapping), gpdjs.crs, drop=False)

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(projection=ccrs.PlateCarree())
cf = ax.contourf(lon, lat, cliped/98,levels=np.arange(520,600,4), transform=proj, cmap=cmaps.radar)
cr = ax.contour(lon,lat, cliped/98,levels=np.arange(520,600,4), colors='k')
ax.clabel(cr, inline=1, fontsize=10, fmt="%i")
ax.add_geometries(shp.geometries(), proj, facecolor='none', edgecolor='k') 
ax.set_extent([100,120,20,40])
plt.show()

方法一参考云台书使:气象绘图加强版(三十)——白化补叙 方法二参考:rioxarray官方文档

完整文件与代码

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 前言
  • 方法一 set_clip_path方法
    • matplotlib 官方函数示例
  • 方法二 rioxarray的rio.clip
    • 拓展:一个省怎么画:使用裁剪后的行政区json进行绘图
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档