Skip to content

天机数据行政区域掩膜操作说明

1. 概述

本文档说明基于 cnmaps 包,对天机 NetCDF 格式模式预报数据按行政区域范围进行掩膜的操作方法。掩膜后将区域外的网格点标记为 NaN,区域内的网格点保留原始值,便于后续按行政区计算区域统计量(区域平均、区域最大/最小等)。

2. cnampas 包获取

cnmaps 是一个基于高德地图数据、支持中国省市县三级行政区划边界获取与空间判定的 Python 包。

安装方式:

Bash
pip install cnmaps

依赖说明cnmaps 会自动安装 cartopygeopandasshapelynumpy 等必要依赖。

3. 数据准备

从天机官网(https://www.tjweather.com/Download)下载 NetCDF 文件。以 2 米气温数据为例:

项目说明
文件2026072900_t2mz_f001.nc
变量t2mz(2 米气温,单位 K)
维度time(1), lat(2400), lon(3200)
覆盖范围中国及周边区域
缺失值_FillValue = 1e+30

4. 核心概念:Mask(掩膜)

cnmapsMapPolygon.make_mask_array(lons, lats) 方法返回一个布尔数组

  • False:该网格点在行政区域内(保留)

  • True:该网格点在行政区域外(丢弃)

因此,应用掩膜的标准写法:

Python
ds_masked = ds.where(~mask_array, np.nan)

即:区域外网格置为 NaN,区域内网格保留原始值。

这样处理便于后续统计——用 np.nanmean()np.nanmax()np.nanmin()nan 系函数自动忽略区域外网格,直接得到区域内统计量。

5. 快速上手:完整流程

Python
import numpy as np
import xarray as xr
from cnmaps import get_adm_maps

# ── 1. 读入数据 ──
ds = xr.open_dataset('2026072900_t2mz_f001.nc')
lon = ds.lon.values
lat = ds.lat.values

# ── 2. 获取行政区边界并生成掩码 ──
polygons = get_adm_maps(level='省', province='河北省', only_polygon=True, wgs84=True)
# get_adm_maps 返回 list,通常只有一个元素
map_polygon = polygons[0]
mask = map_polygon.make_mask_array(lon, lat)  # shape: (len(lat), len(lon))

# ── 3. 应用掩码(区域外 → NaN)──
ds_masked = ds.where(~mask, np.nan)

# ── 4. 区域统计 ──
t2m_mean = np.nanmean(ds_masked.t2mz.values)   # 区域平均
t2m_max  = np.nanmax(ds_masked.t2mz.values)    # 区域最高
t2m_min  = np.nanmin(ds_masked.t2mz.values)    # 区域最低

5.1 形状说明

make_mask_array(lons, lats) 的入参为一维经纬度坐标数组,内部使用 np.meshgrid 构造二维网格后判定。返回的 mask 形状为 (len(lat), len(lon)),与 NetCDF 中 (lat, lon) 的空间维度顺序一致。

6. 分级掩膜示例

6.1 省级

Python
polygons = get_adm_maps(level='省', province='河北省', only_polygon=True, wgs84=True)
mask = polygons[0].make_mask_array(lon, lat)
ds_masked = ds.where(~mask, np.nan)
# 统计
print('河北平均气温:', np.nanmean(ds_masked.t2mz.values))

6.2 市级

Python
polygons = get_adm_maps(level='市', province='河北省', city='唐山市',
                        only_polygon=True, wgs84=True)
mask = polygons[0].make_mask_array(lon, lat)
ds_masked = ds.where(~mask, np.nan)

直辖市属于省级,获取时:level='省', province='北京市' 张家口市属于河北省,正确的省-市参数为 province='河北省', city='张家口市'。省-市-县三级参数均需填写标准中文全称。

6.3 县级

Python
polygons = get_adm_maps(level='区县', province='河北省', city='唐山市',
                        district='曹妃甸区', only_polygon=True, wgs84=True)
mask = polygons[0].make_mask_array(lon, lat)
ds_masked = ds.where(~mask, np.nan)

6.4 多个相邻行政区合并

适用于"京津冀"等跨省联合区域。

Python
# 分别获取各省掩码
polygons_bj = get_adm_maps(level='省', province='北京市', only_polygon=True, wgs84=True)
polygons_tj = get_adm_maps(level='省', province='天津市', only_polygon=True, wgs84=True)
polygons_hb = get_adm_maps(level='省', province='河北省', only_polygon=True, wgs84=True)

mask_bj = polygons_bj[0].make_mask_array(lon, lat)
mask_tj = polygons_tj[0].make_mask_array(lon, lat)
mask_hb = polygons_hb[0].make_mask_array(lon, lat)

# 合并:网格点在任意一个区域内即保留(False)
merged_mask = np.logical_and(mask_bj, np.logical_and(mask_tj, mask_hb))

ds_masked = ds.where(~merged_mask, np.nan)

合并逻辑False 表示"在区域内"。合并时要求所有掩码都为 True(即所有区域外)时才置为 True。等价于在逻辑与运算后,只要有一个掩码判定为 False(区域内),结果就为 False。

7. 参数说明

参数含义示例
level行政级别: / / 区县level='省'
province省/直辖市/自治区全称'河北省''北京市''新疆维吾尔自治区'
city地级市全称(市级/县级需要)'唐山市'
district区县全称(县级需要)'曹妃甸区'
only_polygon=True仅返回多边形,不包含元数据建议始终设为 True
wgs84=True输出 WGS84 坐标系(经纬度)天机数据为经纬度网格,设为 True

名称规范:行政区域名称必须使用标准全称。例如"新疆维吾尔自治区"而非"新疆"。

8. 对数据网格的要求

  • make_mask_array 的一维 lon/lat 数组不需要等间距,但必须与 NetCDF 中的坐标一一对应

  • 数据网格应覆盖目标行政区域,否则掩码会将区域外所有点置为 NaN,区域内可能也无有效网格