前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >常见地图白化方法(一)

常见地图白化方法(一)

作者头像
用户11172986
发布2024-06-20 17:44:57
700
发布2024-06-20 17:44:57
举报
文章被收录于专栏:气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 删除

本文分享自 气python风雨 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 方法一 set_clip_path方法
    • matplotlib 官方函数示例
    • 方法二 rioxarray的rio.clip
      • 拓展:一个省怎么画:使用裁剪后的行政区json进行绘图
      相关产品与服务
      图数据库 KonisGraph
      图数据库 KonisGraph(TencentDB for KonisGraph)是一种云端图数据库服务,基于腾讯在海量图数据上的实践经验,提供一站式海量图数据存储、管理、实时查询、计算、可视化分析能力;KonisGraph 支持属性图模型和 TinkerPop Gremlin 查询语言,能够帮助用户快速完成对图数据的建模、查询和可视化分析。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档