前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Python气象数据处理与可视化

Python气象数据处理与可视化

原创
作者头像
阿巴阿巴-
发布2025-03-10 15:34:49
发布2025-03-10 15:34:49
9800
代码可运行
举报
运行总次数:0
代码可运行

在当今数据驱动的时代,气象数据的获取、处理和可视化已成为气象科学研究和业务应用中不可或缺的环节。Python作为一种功能强大且灵活的编程语言,已经在气象数据处理和可视化领域展现出了巨大的潜力。它不仅提供了丰富的库和工具,如`matplotlib`和`cartopy`,用于数据的科学绘图与可视化,还支持多种数据格式的处理,如`NetCDF`、`GRIB`、`HDF`。此外,Python还能够高效地下载和预处理气象数据,例如利用`cdsapi`和`IDM`批量下载`ERA5`数据。

本文旨在介绍如何使用Python进行气象数据的下载、预处理、统计分析以及科学绘图与可视化。通过本文的介绍,读者可以能够掌握使用Python进行气象数据处理和可视化的基本技能,作者也可以唤起尘封的记忆,整理一下以前的笔记,为进一步的气象研究和应用打下坚实的基础。

数据下载

ERA5数据cdsapi+IDM批量下载

ERA5是由欧洲中期天气预报中心(ECMWF)提供的第五代全球气候大气再分析数据集,覆盖了从1940年1月至今的时期。它由ECMWF的哥白尼气候变化服务(C3S)生产,提供了大量大气、陆地和海洋气候变量的每小时估计值。这些数据覆盖了30公里网格上的地球,并使用137个从地表到80公里高度的高度来解析大气,包括在降低空间和时间分辨率时所有变量的不确定性信息。ERA5将模型数据与来自世界各地的观测数据结合起来,形成一个全球完整的、一致的数据集,取代了其前身ERA-Interim再分析。

CDS平台,即气候数据存储(Climate Data Store),是一个提供气候和气象数据的平台,它允许用户访问和下载各种气候数据集,包括ERA5数据。CDS平台提供了强大的数据管理功能,包括数据收集、存储、整理、清洗和分类等。通过构建高效的数据处理机制,CDS确保了数据的准确性和一致性,为后续的数据分析和算法迭代提供了可靠的基础。为了更直观地展示数据,CDS平台还提供了丰富的数据可视化组件,用户可以根据自己的需求,自由配置可视化界面,实现数据的直观展示和交互。

可以在Datasets里查找需要的数据,收藏经常使用的数据,可以在个人profile里轻松找到。

关于利用cdsapi+IDM批量下载ERA5数据的教程帖子非常多,主要步骤是:

1)注册/登陆后打开CDS上的个人主页,找到API,复制url和key

2)获取API Token后在用户目录下配置.cdsapirc文件

3)下载安装cdsapi第三方库

4)下载安装IDM-Internet Download Manager,IDMan.exe的路径要记住,后面写代码要用

5)获取所需要数据的API request code,如下

6)编写批量下载Python代码

展示主要代码:

代码语言:javascript
代码运行次数:0
复制
import cdsapi
import os
from subprocess import call


def idmDownloader(task_url, folder_path, file_name):
    """
    IDM下载器
    :param task_url: 下载任务地址
    :param folder_path: 存放文件夹
    :param file_name: 文件名
    :return:
    """
    # IDM安装目录
    idm_engine = "C:\\Program Files (x86)\\Internet Download Manager\\IDMan.exe"
    # 将任务添加至队列
    call([idm_engine, '/d', task_url, '/p', folder_path, '/f', file_name, '/a'])
    # 开始任务队列
    call([idm_engine, '/s'])


c = cdsapi.Client()
代码语言:javascript
代码运行次数:0
复制
for date_str in extreme_dates:
    year, month, day = date_str.split('-')
    year_path = os.path.join(path, year)  # 创建每年的文件夹
    os.makedirs(year_path, exist_ok=True)  # 如果文件夹不存在则创建

    filename = f'{variable}.0.25deg.{year}.{month}.{day}.nc'
    output_file_path = os.path.join(year_path, filename)

    # 检查文件是否已存在
    if os.path.exists(output_file_path):
        print(f'文件 {output_file_path} 已存在,跳过下载。')
        continue

    print(f'=======  日期:  {date_str}  =======')

    r = c.retrieve(
        'derived-era5-pressure-levels-daily-statistics',
        {
            'product_type': 'reanalysis',
            'variable': ["geopotential",
                         "specific_humidity",
                         "u_component_of_wind",
                         "v_component_of_wind",
                         "vertical_velocity"],
            'year': [year],
            'month': [month],
            'day': [day],
            "pressure_level": ["500"],
            "daily_statistic": "daily_mean",
            "time_zone": "utc+08:00",
            "frequency": "1_hourly",
            "area": [80, 30, 5, 150]
        },
    )

    url = r.location  # 获取文件下载地址
    idmDownloader(url, year_path, filename)  # 添加进IDM中下载

最后就静待数据自己跑到文件夹里吧~

GPM数据downthemall批量下载

GPM(Global Precipitation Measurement,全球降水测量)数据是由美国国家航空航天局(NASA)和日本宇宙航空研究开发机构(JAXA)联合开展的一项国际卫星任务,旨在提供全球范围内的高精度降水数据。

GPM数据通过多颗卫星的联合观测获得,这些卫星搭载了微波和红外传感器,能够测量降雨和降雪等降水类型。此外,GPM还结合了地面雷达和雨量计的观测数据,进一步提高数据的准确性和可靠性。

下载网站:

代码语言:txt
复制
https://disc.gsfc.nasa.gov/

记得先注册/登陆在检索下载数据。

GPM数据是一日一个文件,大量数据逐个下载的话很繁琐,我尝试了很多办法,发现还是用downthemall插件下载最方便且下载成功率最高。

如果先下载文件链接的txt文件,再逐个下载数据,我反正常遇到网址错误或下载失败的问题。

建议一次性也不要下太多数据,不然出错率蛮高,还得返工。

选择自己需要的数据。

为撒不能收藏啊???


各格式数据介绍

气象海洋数据的存储格式多种多样,不同的格式适用于不同的应用场景和数据处理需求。

netCDF

nc格式数据非常常见,文件中包含数据的元信息(如变量名称、单位、坐标轴等),便于数据的读取和理解。

支持大数据量存储,适合存储多维气象和海洋数据(如温度、湿度、风场等)。

可以print出来看看内容,也可以直接使用panoply可视化出来。

GRIB

GRIB(General Regularly-distributed Information in Binary form)是由世界气象组织(WMO)设计和维护的一种用于存储和传输网格数据的标准数据格式。它是一种自描述的二进制压缩格式,主要用于气象和海洋科学领域,尤其适用于存储数值天气预报模型的输出数据。GRIB主要用于存储规则格点数据,适用于气象模型输出、卫星数据等。

GRIB文件由多个“报文”(Message)组成,每个报文包含一套完整的数据及其描述信息。报文结构包括多个部分(Section)。

pygrib 和 cfgrib:Python库,用于在Python环境中处理GRIB数据。

HDF

HDF(Hierarchical Data Format,层次数据格式)是一种用于存储和管理大规模、复杂科学数据的自描述、多对象的二进制文件格式。它广泛应用于气象、海洋、生物、天文学等多个科学领域。

HDF文件采用类似文件系统的层次结构,包含“组”(Group)和“数据集”(Dataset)。组类似于文件夹,用于组织数据;数据集类似于文件,用于存储实际数据。

HDF文件由多个“组”和“数据集”组成,每个数据集包含实际数据和与之相关的元数据。例如,一个气象数据的HDF文件可能包含多个组,每个组代表不同的气象变量(如温度、风速等),每个组下又有多个数据集,存储不同时间或空间的数据。

HDF有多个版本,其中HDF5是当前主流版本。HDF5提供了一个更高效、更灵活的数据模型,支持复杂的多维数据结构和高效的I/O操作。

常用的处理工具:

h5py:Python中用于操作HDF5文件的库,支持读写HDF5文件。

HDFView:一个可视化工具,用于浏览和编辑HDF文件。

GDAL:用于地理空间数据处理的工具,支持HDF格式的读取。

shapefile

Shapefile 是一种广泛使用的地理空间数据格式,主要用于存储地理信息系统的(GIS)矢量数据,如点、线、多边形等几何对象及其属性信息。它由美国环境系统研究所公司(ESRI,Environmental Systems Research Institute)开发,并已成为地理空间数据交换的事实标准。

Shapefile 实际上是一个文件集合,每个 Shapefile 至少包含以下三个核心文件:

1).shp 文件

内容:存储几何对象(点、线、多边形)的二进制数据。

作用:定义地理空间数据的几何形状,如经纬度坐标、几何拓扑结构等。

2).shx 文件

内容:索引文件,用于快速定位 .shp 文件中的几何对象。

作用:提高数据读取效率,尤其在处理大规模数据时。

3).dbf 文件

内容:以 dBase IV 格式存储几何对象的属性信息。

作用:为每个几何对象提供描述性信息,如名称、类别、数值等。


Shapefile 支持点(Point)、线(Polyline)、多边形(Polygon)等多种几何类型,能够满足大多数地理空间数据的存储需求。

不同的shapefile文件储存格式有所不同,重要的是需要找到所需区域的多边形数据存储的位置。

数据预处理

打开数据

在Python中,可以使用多种库来打开和查看NetCDF(.nc)文件。

1)xarray

代码语言:javascript
代码运行次数:0
复制
import xarray as xr

# 打开文件
ds = xr.open_dataset('example.nc')

# 查看数据集的基本信息
print(ds)

# 读取某个变量的数据
temperature = ds['temperature'].values
print("Temperature Data:", temperature)

# 关闭数据集
ds.close()

2)netCDF4

代码语言:javascript
代码运行次数:0
复制
import netCDF4 as nc

# 打开文件
dataset = nc.Dataset('example.nc', 'r')

# 查看文件中的维度和变量
print("Dimensions:", dataset.dimensions.keys())
print("Variables:", dataset.variables.keys())

# 读取某个变量的数据
temperature = dataset.variables['temperature'][:]
print("Temperature Data:", temperature)

# 关闭文件
dataset.close()

索引

1)netCDF4索引:

使用数组切片语法(如[0, :, :])直接索引数据。

需要明确变量的维度顺序(通常是时间、纬度、经度)。

代码语言:javascript
代码运行次数:0
复制
import netCDF4 as nc

# 打开NetCDF文件
dataset = nc.Dataset('example.nc', 'r')

# 查看文件中的变量
print("Variables:", dataset.variables.keys())

# 索引并读取特定变量的数据
temperature = dataset.variables['temperature'][:]  # 读取所有数据
temperature_at_time_0 = dataset.variables['temperature'][0, :, :]  # 索引时间维度的第一个时间点
temperature_at_lat_0_lon_0 = dataset.variables['temperature'][:, 0, 0]  # 索引特定经纬度点

print("Temperature Data:", temperature)
print("Temperature at Time 0:", temperature_at_time_0)
print("Temperature at Lat 0, Lon 0:", temperature_at_lat_0_lon_0)

# 关闭文件
dataset.close()

2)xarray索引:

使用.isel()方法进行基于位置的索引。

支持更直观的多维索引,适合复杂数据操作。

代码语言:javascript
代码运行次数:0
复制
import xarray as xr

# 打开NetCDF文件
ds = xr.open_dataset('example.nc')

# 查看数据集信息
print(ds)

# 索引特定变量的数据
temperature = ds['temperature']  # 获取温度变量
temperature_at_time_0 = temperature.isel(time=0)  # 索引时间维度的第一个时间点
temperature_at_lat_0_lon_0 = temperature.isel(lat=0, lon=0)  # 索引特定经纬度点

print("Temperature Data:", temperature)
print("Temperature at Time 0:", temperature_at_time_0)
print("Temperature at Lat 0, Lon 0:", temperature_at_lat_0_lon_0)

# 关闭数据集
ds.close()

裁剪

slice是一个内置对象,用于表示序列(如列表、元组、字符串等)的切片操作。它通常用于提取序列中的一部分数据,而不需要重新创建整个序列。

代码语言:javascript
代码运行次数:0
复制
slice(start, stop, step)

裁剪国界、省界、市界等需要借助shapefile文件,也就是白化。

白化

白化、掩膜、按区域裁剪,感觉都差不多,即将不需要的研究区域白化处理,凸显出研究区域。

介绍一种白化裁剪方法。这个方法比较简单粗暴。

代码语言:javascript
代码运行次数:0
复制
import rioxarray
import geopandas
from shapely. geometry import mapping
#设置数据集的空间维度(也称为地理或空间坐标)并编写坐标参考系统(crs)。 EPSG4326 坐标系,也称为 WGS 84(世界大地测量系统 1984),是地理数据常用的坐标系
data.rio.set_spatial_dims(x_dim="lon", y_dim="lat", inplace=True)    # x_dim具体是什么,看自己的nc文件变量名
data.rio.write_crs("epsg:4326", inplace=True)
# 将非空间变量设置为坐标,避免干扰裁剪操作
data = data.set_coords(["time_bnds"])  # 如果nc文件里有lon_bnds啥的也要加上

hunan = geopandas.read_file('C:/Users/lenovo/Desktop/湖南无子区域/湖南省行政边界.shp', crs="epsg:4326")  # 该shp只含湖南省界
clipped = data.rio.clip(hunan.geometry.apply(mapping), hunan.crs, drop=True)

print(clipped)

白化主要有两种思路:

1)先白化数据,在绘图

这样画出来的图不太好看,边界像锯齿,磕巴。但如果只要研究区域内的数据,就得先处理数据。

2)先画矩形区域,再白化图形

这样画图边界更好看,如果只有可视化需求,建议先画图再白化。

插值

插值的方法很多。

1)最近邻插值(Nearest Neighbor Interpolation)

最近邻插值是一种简单的插值方法,通过找到目标点最近的观测站点,直接将该站点的值赋予目标点。这种方法的优点是计算速度快,但插值结果较为粗糙,不适用于需要平滑过渡的场景。

2)反距离加权插值(Inverse Distance Weighting, IDW)

反距离加权插值是一种基于距离的加权平均方法,权重与距离的倒数成正比。这种方法适用于气象数据的插值,尤其是当观测站点分布不均匀时。它能够生成较为平滑的结果,但可能会在边界处出现偏差。

3)克里金插值(Kriging)

克里金插值是一种基于统计学的插值方法,适用于具有空间相关性的数据。它通过建模半方差函数来估计空间相关性,并生成最优的无偏插值结果。克里金插值能够提供更精确的插值结果,但计算复杂度较高。

4)样条插值(Spline Interpolation)

样条插值是一种基于多项式的插值方法,能够生成平滑的曲线或曲面。它适用于需要高精度插值的场景,但可能会在数据边界处出现震荡。

5)多元回归分析法(Multiple Regression Analysis)

多元回归分析法是一种基于统计模型的插值方法,适用于具有多个影响因素的数据。它通过建立线性或非线性模型来预测目标变量的值,适用于气象要素的时空插值。


完整示例代码:

代码语言:javascript
代码运行次数:0
复制
#coding=gbk
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# 1. 打开数据
file_path = r'C:/path/to/your/data.nc'  # 替换为你的NC文件路径
ds = xr.open_dataset(file_path)

# 打印数据集信息
print(ds)

# 2. 索引数据
# 假设数据集中有一个变量名为'temperature',维度为(time, lat, lon)
temperature = ds['temperature']  # 提取温度变量
print(temperature)

# 3. 裁剪数据
# 假设需要裁剪到特定区域(如纬度20°-40°,经度100°-120°)
lat_range = slice(20, 40)  # 纬度范围
lon_range = slice(100, 120)  # 经度范围
temperature_cropped = temperature.sel(lat=lat_range, lon=lon_range)
print(temperature_cropped)

# 4. 白化(掩膜处理)
# 假设需要掩膜掉海洋区域(海洋值为NaN)
# 这里假设海洋区域的温度值为NaN
temperature_masked = temperature_cropped.where(~np.isnan(temperature_cropped))
print(temperature_masked)

# 5. 插值
# 假设需要将数据插值到更精细的网格(如0.1°×0.1°)
# 原始网格
lon_original = temperature_masked.lon.values
lat_original = temperature_masked.lat.values

# 新网格
new_lon = np.linspace(lon_original.min(), lon_original.max(), int((lon_original.max() - lon_original.min()) / 0.1))
new_lat = np.linspace(lat_original.min(), lat_original.max(), int((lat_original.max() - lat_original.min()) / 0.1))
new_lon, new_lat = np.meshgrid(new_lon, new_lat)

# 插值(使用线性插值)
temperature_interpolated = griddata(
    (lon_original.flatten(), lat_original.flatten()),  # 原始网格点
    temperature_masked.values.flatten(),  # 原始数据
    (new_lon, new_lat),  # 新网格点
    method='linear'  # 插值方法:linear, nearest, cubic
)

# 6. 可视化结果
plt.figure(figsize=(10, 6))
plt.contourf(new_lon, new_lat, temperature_interpolated, levels=20, cmap='coolwarm')
plt.colorbar(label='Temperature (°C)')
plt.title('Interpolated Temperature')
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.show()

# 7. 保存处理后的数据(可选)
output_path = r'C:/path/to/your/processed_data.nc'  # 替换为输出路径
temperature_interpolated_ds = xr.Dataset(
    {
        'temperature': (['lat', 'lon'], temperature_interpolated)
    },
    coords={
        'lon': new_lon[0, :],  # 新经度坐标
        'lat': new_lat[:, 0]  # 新纬度坐标
    }
)
temperature_interpolated_ds.to_netcdf(output_path)
print(f"处理后的数据已保存至:{output_path}")

数据统计分析

numpy

NumPy 是Python中用于科学计算的基础库,提供了高性能的多维数组对象(ndarray)以及用于操作这些数组的工具。

xarray

xarray 是一个基于 NumPy 的库,专门用于处理多维数据(如气象、海洋数据)。它提供了更高级的接口,使得数据操作更加直观和方便。

sklearn

scikit-learn 是一个广泛使用的机器学习库,提供了简单且高效的工具用于数据挖掘和数据分析。它提供了多种监督学习(如线性回归、逻辑回归、支持向量机、决策树等)和无监督学习(如聚类、降维等)算法

科学绘图与可视化

基本思路是处理好数据,确定想要展现出的图片形式,画就完了。panoply也可以一键可视化nc、hdf等数据。

matplotlib

matplotlib是Python中最常用的科学绘图库之一,提供了丰富的绘图功能,可以生成各种静态、动画和交互式图表和各种子图排布,非常灵活。

代码语言:javascript
代码运行次数:0
复制
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes[0, 0].plot(x, np.sin(x), label="sin(x)")
axes[0, 1].plot(x, np.cos(x), label="cos(x)")
axes[1, 0].plot(x, np.tan(x), label="tan(x)")
axes[1, 1].plot(x, np.exp(-x), label="exp(-x)")
for ax in axes.flatten():
    ax.legend()
    ax.grid(True)
plt.tight_layout()
plt.show()

cartopy

cartopy是一个基于matplotlib的地理空间数据可视化库,专门用于绘制地图和地理数据。它提供了丰富的地图投影和地理数据处理功能,非常适合气象、海洋和地理科学领域。

支持多种地图投影,可以利用matplotlib的绘图功能进行定制化。

代码语言:javascript
代码运行次数:0
复制
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt

# 创建地图
fig, ax = plt.subplots(figsize=(10, 6), subplot_kw={"projection": ccrs.PlateCarree()})

# 添加地图元素
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, linestyle=":")
ax.add_feature(cfeature.LAND, facecolor="lightgray")
ax.add_feature(cfeature.OCEAN, facecolor="lightblue")

# 设置地图范围
ax.set_extent([70, 140, 15, 55], crs=ccrs.PlateCarree())  # 经纬度范围

# 添加标题
ax.set_title("China Map", fontsize=16)

plt.show()

绘制地理数据

代码语言:javascript
代码运行次数:0
复制
import xarray as xr
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

# 加载NetCDF数据
ds = xr.open_dataset("example.nc")
temperature = ds['temperature'].isel(time=0)

# 创建地图
fig, ax = plt.subplots(figsize=(10, 6), subplot_kw={"projection": ccrs.PlateCarree()})

# 添加地图元素
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, linestyle=":")
ax.add_feature(cfeature.LAND, facecolor="lightgray")

# 绘制数据
temperature.plot(ax=ax, transform=ccrs.PlateCarree(), cmap="coolwarm", add_colorbar=True)

# 设置地图范围
ax.set_extent([70, 140, 15, 55], crs=ccrs.PlateCarree())

# 添加标题
ax.set_title("Temperature Distribution", fontsize=16)

plt.show()

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据下载
    • ERA5数据cdsapi+IDM批量下载
    • GPM数据downthemall批量下载
  • 各格式数据介绍
    • netCDF
    • GRIB
    • HDF
    • shapefile
  • 数据预处理
    • 打开数据
    • 索引
    • 裁剪
    • 白化
    • 插值
  • 数据统计分析
    • numpy
    • xarray
    • sklearn
  • 科学绘图与可视化
    • matplotlib
    • cartopy
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档