)
从FTP下载到可视化一条龙处理GDAS1气象数据的Python实战气象数据是研究气候变化、天气预报和环境监测的重要基础。对于刚接触气象数据分析的研究者来说如何获取、处理和可视化专业气象数据往往是一个令人头疼的问题。本文将带你从零开始完整掌握GDAS1气象数据的全流程处理方法包括FTP下载、数据解析、计算处理和可视化展示。1. GDAS1气象数据基础认知GDAS1Global Data Assimilation System version 1是由美国国家环境预报中心(NCEP)开发的全球数据同化系统生成的气象数据集。这套数据每3小时更新一次覆盖全球范围空间分辨率为1度经纬度网格(360×181)是气象研究和空气质量模拟的重要数据源。GDAS1数据采用GRIB格式存储这种二进制格式专为气象数据设计具有高效的存储性能。但同时也带来了处理上的挑战——GRIB文件不能像普通文本文件那样直接读取需要专门的库进行解码。提示GRIB(GRIdded Binary)是世界气象组织(WMO)开发的一种用于存储和传输网格化气象数据的二进制文件格式广泛应用于气象领域。数据文件按照特定规则命名例如gdas1.nov22.w3gdas1数据类型标识nov月份缩写(11月)22年份缩写(2022年)w3表示该文件包含当月15-21日的数据完整的周次划分规则如下周次代码包含日期范围w1当月1-7日w28-14日w315-21日w422-28日w529日至月末2. 数据获取与准备工作2.1 从FTP服务器下载GDAS1数据NOAA通过FTP服务器公开提供历史GDAS1数据最新数据可通过以下地址获取ftp_url ftp://arlftp.arlhq.noaa.gov/archives/gdas1/对于Python用户推荐使用ftplib库进行文件下载。以下是完整的下载脚本示例import ftplib import os def download_gdas1(year, month, week, save_dir): 下载指定时间段的GDAS1数据 Args: year (int): 年份如2022 month (int): 月份1-12 week (int): 周次1-5 month_abbr [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec][month-1] filename fgdas1.{month_abbr}{str(year)[-2:]}.w{week} try: with ftplib.FTP(arlftp.arlhq.noaa.gov) as ftp: ftp.login() ftp.cwd(archives/gdas1) if not os.path.exists(save_dir): os.makedirs(save_dir) local_path os.path.join(save_dir, filename) with open(local_path, wb) as f: ftp.retrbinary(fRETR {filename}, f.write) print(f成功下载: {filename}) except Exception as e: print(f下载失败: {e}) # 示例下载2022年11月第三周的数据 download_gdas1(2022, 11, 3, ./gdas_data)2.2 数据解析工具准备由于GDAS1使用特殊的GRIB格式我们需要专门的库来读取数据。推荐使用ARLreader这个Python库# 安装ARLreader库 git clone https://github.com/martin-rdz/ARLreader cd ARLreader pip install .注意ARLreader目前仅支持Python 3.6环境。如果遇到依赖冲突建议使用conda创建独立环境conda create -n gdas_env python3.6 conda activate gdas_env3. 数据处理与分析实战3.1 数据读取与字段解析GDAS1包含丰富的气象要素主要分为地面观测和高空观测两大类地面观测字段示例TEMP2米高度气温(K)RH2M2米高度相对湿度(%)PRSS地表气压(Pa)TPP66小时累计降水量(m)高空观测字段示例UWND纬向风速(m/s)VWND经向风速(m/s)HGHT位势高度(m)TEMP温度(K)以下代码演示如何读取特定高度层的数据import ARLreader as Ar import numpy as np def read_gdas_data(filepath, date, hour, level, field): 读取GDAS1文件中指定时间、高度和字段的数据 Args: filepath: GDAS1文件路径 date: 日期如221115表示2022年11月15日 hour: 小时0-21(3小时间隔) level: 高度层代码 field: 字段名称 Returns: recinfo: 记录信息对象 grid: 网格信息对象 data: 二维numpy数组 reader Ar.reader(filepath) recinfo, grid, data reader.load_heightlevel(date, hour, level, field) if recinfo.fc -1: print(警告该时刻数据不可用) return None, None, None return recinfo, grid, data # 示例读取2022年11月15日00UTC 850hPa温度数据 filepath ./gdas_data/gdas1.nov22.w3 recinfo, grid, temp_850 read_gdas_data(filepath, 221115, 0, 850, TEMP)3.2 计算日均值气象分析中经常需要计算日平均值。由于GDAS1是每3小时一次的数据我们可以通过时间平均来获取日均值def calculate_daily_mean(filepath, date, level, field): 计算指定日期、高度和字段的日均值 Args: filepath: GDAS1文件路径 date: 日期字符串如221115 level: 高度层代码 field: 字段名称 Returns: mean_data: 日均值二维数组 lats: 纬度数组 lons: 经度数组 data_list [] reader Ar.reader(filepath) for hour in [0, 3, 6, 9, 12, 15, 18, 21]: recinfo, grid, data reader.load_heightlevel(date, hour, level, field) if recinfo.fc ! -1: # 忽略不可用数据 data_list.append(data) if not data_list: return None, None, None mean_data np.mean(data_list, axis0) return mean_data, grid.lats, grid.lons # 计算2022年11月15日850hPa温度日均值 mean_temp, lats, lons calculate_daily_mean(filepath, 221115, 850, TEMP)4. 数据存储与可视化4.1 输出为NetCDF格式NetCDF是气象领域广泛使用的数据格式支持多维数据和丰富的元数据。以下是将处理结果保存为NetCDF的完整代码from netCDF4 import Dataset import numpy as np def save_to_netcdf(data, lats, lons, field, output_path): 将处理结果保存为NetCDF文件 Args: data: 二维数据数组 lats: 纬度数组 lons: 经度数组 field: 字段名称 output_path: 输出文件路径 with Dataset(output_path, w, formatNETCDF4) as nc: # 创建维度 lat_dim nc.createDimension(lat, len(lats)) lon_dim nc.createDimension(lon, len(lons)) # 创建变量 latitudes nc.createVariable(lat, f4, (lat,)) latitudes.units degrees_north latitudes.long_name latitude longitudes nc.createVariable(lon, f4, (lon,)) longitudes.units degrees_east longitudes.long_name longitude var nc.createVariable(field, f4, (lat, lon)) var.units get_units(field) # 根据字段获取单位 # 写入数据 latitudes[:] lats longitudes[:] lons var[:, :] data print(f成功保存: {output_path}) def get_units(field): 获取字段对应单位 units_dict { TEMP: K, RH2M: %, PRSS: Pa, UWND: m/s, VWND: m/s, HGHT: m } return units_dict.get(field, unknown) # 示例保存日均温度数据 save_to_netcdf(mean_temp, lats, lons, TEMP, daily_mean_temp.nc)4.2 数据可视化展示使用matplotlib和cartopy库可以创建专业的气象图表。以下是绘制全球温度场的示例import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature from netCDF4 import Dataset def plot_global_temp(nc_file, level850): 绘制全球温度场 Args: nc_file: NetCDF文件路径 level: 高度层(用于标题显示) with Dataset(nc_file) as nc: temp nc.variables[TEMP][:] lats nc.variables[lat][:] lons nc.variables[lon][:] fig plt.figure(figsize(15, 8)) ax fig.add_subplot(1, 1, 1, projectionccrs.PlateCarree()) # 添加地理要素 ax.add_feature(cfeature.LAND) ax.add_feature(cfeature.OCEAN) ax.add_feature(cfeature.COASTLINE) ax.add_feature(cfeature.BORDERS, linestyle:) # 绘制温度场 contour ax.contourf(lons, lats, temp - 273.15, # 转换为摄氏度 levels20, cmapcoolwarm, transformccrs.PlateCarree()) # 添加色标 cbar plt.colorbar(contour, axax, orientationhorizontal, pad0.05) cbar.set_label(Temperature (°C)) # 设置标题和网格线 ax.set_title(fGlobal Temperature at {level}hPa, fontsize16) ax.gridlines(draw_labelsTrue) plt.tight_layout() plt.savefig(global_temp.png, dpi300, bbox_inchestight) plt.show() # 示例可视化之前保存的温度数据 plot_global_temp(daily_mean_temp.nc, level850)5. 进阶技巧与性能优化5.1 批量处理多日数据实际研究中通常需要处理长时间序列数据。以下是批量处理多日数据的优化方案import glob from concurrent.futures import ProcessPoolExecutor def batch_process(input_dir, output_dir, level, field, start_date, end_date): 批量处理指定日期范围内的数据 Args: input_dir: 原始GDAS1文件目录 output_dir: 输出目录 level: 高度层 field: 字段名称 start_date: 开始日期(如221101) end_date: 结束日期(如221130) files sorted(glob.glob(f{input_dir}/gdas1.*)) dates generate_date_range(start_date, end_date) # 使用多进程加速处理 with ProcessPoolExecutor(max_workers4) as executor: for file in files: for date in dates: executor.submit(process_single_day, file, date, level, field, output_dir) def process_single_day(file, date, level, field, output_dir): 处理单日数据并保存结果 try: mean_data, lats, lons calculate_daily_mean(file, date, level, field) if mean_data is not None: output_path f{output_dir}/{field}_{date}.nc save_to_netcdf(mean_data, lats, lons, field, output_path) except Exception as e: print(f处理{date}数据失败: {e}) def generate_date_range(start, end): 生成日期序列 # 实现略... pass5.2 使用Xarray优化工作流对于熟悉PyData生态的用户可以结合xarray和dask实现更高效的数据处理import xarray as xr import dask.array as da def process_with_xarray(file_pattern, field): 使用xarray处理多个GDAS1文件 # 创建处理管道 ds xr.open_mfdataset(file_pattern, enginearlreader, concat_dimtime, combinenested, parallelTrue) # 计算月平均 monthly_mean ds[field].groupby(time.month).mean(dimtime) # 保存结果 monthly_mean.to_netcdf(monthly_mean.nc) return monthly_mean提示xarray的open_mfdataset可以并行读取多个文件特别适合处理大规模气象数据集。结合dask可以实现内存友好的分布式计算。