用Python分析全球水资源变化:基于WaterGAP模型月数据(1901-2019)的完整流程
用Python分析全球水资源变化:基于WaterGAP模型月数据(1901-2019)的完整流程
当我们需要研究全球水资源的长期变化趋势时,WaterGAP模型提供的月尺度数据无疑是一个宝贵的资源。这份跨越119年的数据集,记录了从1901年到2019年间全球水循环的详细变化,包括地表水、地下水、土壤水等多种水储量指标。本文将带领读者从数据获取开始,一步步完成数据处理、分析和可视化的全过程,最终生成专业的水资源变化趋势图。
1. 环境准备与数据获取
在开始分析之前,我们需要搭建一个合适的工作环境。推荐使用Anaconda创建独立的Python环境,确保依赖包的版本一致性。以下是核心依赖包及其作用:
# 创建conda环境
conda create -n watergap python=3.9
conda activate watergap
# 安装核心包
pip install xarray dask netCDF4 pandas numpy matplotlib cartopy
WaterGAP数据可以从Pangaea数据仓库获取。数据集通常以NetCDF格式存储,这种格式特别适合存储多维科学数据。我们可以使用 xarray 库高效地处理这些数据,它提供了类似pandas的接口,但专门为多维数组设计。
import xarray as xr
# 示例数据加载
ds = xr.open_dataset('watergap_22d_gswp3-w5e5_histsoc_tws_monthly_1901_2019.nc4')
2. 数据预处理与质量控制
原始数据往往需要经过预处理才能用于分析。WaterGAP数据虽然已经过质量控制,但我们仍需进行一些基本检查和处理。
2.1 数据完整性检查
首先检查数据的时间覆盖范围和空间分辨率:
print(f"时间范围: {ds.time.min().values} 到 {ds.time.max().values}")
print(f"空间分辨率: {ds.lon[1].values - ds.lon[0].values} 度")
print(f"可用变量: {list(ds.data_vars)}")
2.2 缺失值处理
WaterGAP数据中的缺失值通常用特定值标记(如-9999),我们需要将其替换为NaN:
ds['tws'] = ds['tws'].where(ds['tws'] != -9999)
2.3 时间一致性检查
确保时间轴连续且无跳跃:
import pandas as pd
# 检查时间间隔是否一致
time_diffs = pd.Series(ds.time.values[1:]) - pd.Series(ds.time.values[:-1])
print(f"时间间隔是否一致: {all(time_diffs == time_diffs[0])}")
3. 区域选择与时间序列分析
针对特定区域的分析是水资源研究的常见需求。下面以长江流域为例,展示如何提取区域数据并进行分析。
3.1 定义区域边界
长江流域的大致经纬度范围:
yangtze_bbox = {
'lon_min': 90,
'lon_max': 122,
'lat_min': 24,
'lat_max': 35
}
3.2 区域数据提取
使用xarray的sel方法提取区域数据:
yangtze_ds = ds.sel(
lon=slice(yangtze_bbox['lon_min'], yangtze_bbox['lon_max']),
lat=slice(yangtze_bbox['lat_max'], yangtze_bbox['lat_min'])
)
3.3 时间序列聚合
计算区域平均时间序列:
yangtze_ts = yangtze_ds['tws'].mean(dim=['lon', 'lat'])
4. 趋势分析与可视化
长期趋势分析是水资源研究的核心内容。下面介绍几种常用的分析方法。
4.1 年际变化趋势
首先将月数据聚合为年平均值:
yearly_mean = yangtze_ts.groupby('time.year').mean()
使用线性回归计算趋势:
from scipy.stats import linregress
years = yearly_mean.year.values
values = yearly_mean.values
slope, intercept, r_value, p_value, std_err = linregress(years, values)
print(f"趋势: {slope*10:.2f} mm/10年, p值: {p_value:.4f}")
4.2 可视化展示
使用matplotlib绘制时间序列和趋势线:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
plt.figure(figsize=(12, 6))
plt.plot(yearly_mean.year, yearly_mean, label='年平均值')
plt.plot(years, intercept + slope*years, 'r', label='趋势线')
plt.title('长江流域总水储量年际变化 (1901-2019)')
plt.xlabel('年份')
plt.ylabel('总水储量 (mm)')
plt.legend()
plt.grid()
plt.show()
5. 空间分布与变化模式
除了时间序列分析,空间分布特征也是理解水资源变化的重要方面。
5.1 多年平均空间分布
计算整个时期的平均水储量:
mean_tws = ds['tws'].mean(dim='time')
5.2 变化趋势的空间分布
计算每个格点的线性趋势:
from scipy.stats import linregress
def calc_trend(ts):
years = np.arange(len(ts))
slope, _, _, _, _ = linregress(years, ts)
return slope * len(years) # 总变化量
trend = xr.apply_ufunc(
calc_trend,
ds['tws'].chunk({'lat': 10, 'lon': 10}),
input_core_dims=[['time']],
output_core_dims=[[]],
vectorize=True
)
5.3 空间可视化
使用cartopy绘制空间分布图:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
proj = ccrs.PlateCarree()
fig = plt.figure(figsize=(15, 8))
ax = fig.add_subplot(111, projection=proj)
# 添加地理要素
ax.add_feature(cfeature.LAND)
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, linestyle=':')
# 绘制趋势
im = trend.plot(ax=ax, transform=proj, cmap='coolwarm',
cbar_kwargs={'label': '水储量变化 (mm/世纪)'})
ax.set_title('全球总水储量变化趋势 (1901-2019)')
plt.show()
6. 多变量分析与相关性研究
水资源系统各分量之间存在复杂的相互作用,多变量分析有助于理解这些关系。
6.1 数据整合
加载多个相关变量:
variables = ['tws', 'groundwstor', 'soilmoist', 'swe']
datasets = {}
for var in variables:
filename = f'watergap_22d_gswp3-w5e5_histsoc_{var}_monthly_1901_2019.nc4'
datasets[var] = xr.open_dataset(filename)[var]
6.2 区域平均时间序列
计算长江流域各变量的年平均值:
yearly_means = {}
for var, da in datasets.items():
region_da = da.sel(
lon=slice(yangtze_bbox['lon_min'], yangtze_bbox['lon_max']),
lat=slice(yangtze_bbox['lat_max'], yangtze_bbox['lat_min'])
)
yearly_means[var] = region_da.groupby('time.year').mean()
6.3 相关性分析
计算各变量间的相关系数:
import pandas as pd
df = pd.DataFrame(yearly_means)
corr_matrix = df.corr()
print("变量间相关系数矩阵:")
print(corr_matrix)
7. 高级分析与应用
在前面的基础上,我们可以进行更深入的分析,为水资源管理提供科学依据。
7.1 干旱事件识别
定义基于TWS的干旱指标:
# 计算标准化异常
tws_mean = yearly_means['tws'].mean()
tws_std = yearly_means['tws'].std()
tws_anomaly = (yearly_means['tws'] - tws_mean) / tws_std
# 识别严重干旱年份
drought_years = tws_anomaly[tws_anomaly < -1.5]
print(f"严重干旱年份: {list(drought_years.index)}")
7.2 变化点检测
使用Pettitt检验检测突变点:
from pyhomogeneity import pettitt_test
result = pettitt_test(yearly_means['tws'].values)
print(f"突变点年份: {years[result.cp]}, 显著性: {result.p:.3f}")
7.3 未来情景预测
基于历史趋势的简单预测:
future_years = np.arange(2020, 2051)
future_tws = intercept + slope * future_years
plt.figure(figsize=(10, 5))
plt.plot(years, yearly_means['tws'], label='观测')
plt.plot(future_years, future_tws, '--', label='预测')
plt.title('长江流域总水储量预测')
plt.xlabel('年份')
plt.ylabel('总水储量 (mm)')
plt.legend()
plt.grid()
plt.show()
8. 性能优化与大数据处理
当处理全球长时间序列数据时,性能优化至关重要。以下是几种有效的优化策略。
8.1 使用Dask进行并行计算
import dask.array as da
# 分块加载数据
ds = xr.open_mfdataset('watergap_*.nc4', chunks={'time': 120, 'lat': 100, 'lon': 100})
# 并行计算
mean_tws = ds['tws'].mean(dim='time').compute()
8.2 内存优化技巧
对于大型计算,可以采取以下策略:
- 使用
xarray的chunk方法控制内存使用 - 及时删除不再需要的中间变量
- 使用
dask的persist方法缓存常用数据
# 示例:分块计算
chunked = ds['tws'].chunk({'time': 120, 'lat': 50, 'lon': 50})
result = chunked.groupby('time.year').mean().compute()
8.3 结果存储优化
将中间结果保存为Zarr格式,提高后续读取效率:
# 保存为Zarr格式
ds.to_zarr('watergap_tws.zarr')
# 从Zarr读取
ds_zarr = xr.open_zarr('watergap_tws.zarr')
更多推荐
所有评论(0)