Windows环境下无法使用Xesmf时,如何将Xarray中的旋转网格数据插值到规则经纬度网格
Windows环境下无法使用Xesmf时,如何将Xarray中的旋转网格数据插值到规则经纬度网格
我太懂你在Windows上没法用xesmf的憋屈了!之前处理旋转网格数据时也碰到过一模一样的问题,给你几个不用xesmf也能搞定的方案,亲测在Windows上完全可行:
先说说你之前操作的问题所在
旋转网格的数据集里,latitude和longitude一般是二维变量(和x、y这类旋转网格的笛卡尔坐标一一对应),而不是一维的坐标维度。你直接用dat.interp(latitude=np.arange(...))是无效的——因为xarray.interp是基于数据集的一维坐标维度来做插值的,没法直接识别二维的经纬度变量,这就是为什么你得到的结果有缺失点、网格还不对的原因。
方案一:用Scipy的griddata做插值(最推荐)
Scipy在Windows上安装毫无压力,用它的griddata可以直接把二维经纬度的点数据插值到规则网格上,步骤很清晰:
from scipy.interpolate import griddata import xarray as xr import numpy as np # 替换成你实际的数据集和变量名 # 假设原数据集是dat,要插值的变量是'temp' # 1. 提取原数据中的所有有效经纬度点和对应数据 orig_lat = dat['latitude'].values.flatten() orig_lon = dat['longitude'].values.flatten() orig_data = dat['temp'].values.flatten() # 过滤掉原数据中的缺失值点(避免插值报错) valid_mask = ~np.isnan(orig_data) orig_lat = orig_lat[valid_mask] orig_lon = orig_lon[valid_mask] orig_data = orig_data[valid_mask] # 2. 生成你需要的规则经纬度网格 lat_regular = np.arange(8, 24, 0.001) lon_regular = np.arange(102, 110, 0.001) # 转换成网格点矩阵 lon_grid, lat_grid = np.meshgrid(lon_regular, lat_regular) # 3. 执行插值 # 方法可选'nearest'(最快,无平滑)、'linear'(线性插值)、'cubic'(三次插值,平滑效果好) interpolated_data = griddata( (orig_lon, orig_lat), # 注意顺序是(经度, 纬度),要和后面的网格矩阵对应 orig_data, (lon_grid, lat_grid), method='nearest', # 如果需要填充超出原数据范围的区域,可以加fill_value参数,比如fill_value=-9999 ) # 4. 把插值结果转回Xarray Dataset,方便后续处理 result_ds = xr.Dataset( { 'temp': (['latitude', 'longitude'], interpolated_data) }, coords={ 'latitude': lat_regular, 'longitude': lon_regular } )
方案二:先构建规则网格模板,再用xarray的interp_like(适合原数据有一维旋转坐标的情况)
如果你的原数据集有x和y这类一维的旋转网格坐标(比如笛卡尔坐标),可以先把经纬度作为x和y的二维坐标,然后用规则网格模板来插值:
import xarray as xr import numpy as np # 1. 构建规则经纬度网格的模板数据集 lat_reg = np.arange(8, 24, 0.001) lon_reg = np.arange(102, 110, 0.001) template_ds = xr.Dataset( coords={ 'latitude': lat_reg, 'longitude': lon_reg } ) # 2. 注意:这里需要原数据集的经纬度是x和y的二维坐标 # 先把原数据的经纬度设置为x和y的坐标 dat = dat.assign_coords( latitude=(['x', 'y'], dat['latitude'].values), longitude=(['x', 'y'], dat['longitude'].values) ) # 3. 用interp_like插值,指定方法 # 这个方法的前提是原数据的经纬度可以通过x/y坐标映射到规则网格,效果可能不如Scipy的griddata稳定 result_ds = dat.interp_like(template_ds, method='nearest')
一些额外的小提醒
- 你设置的规则网格分辨率太高了:0.001度的步长,光纬度就有16000个点,经度8000个点,总共有1.28亿个点,插值会非常慢,还占内存。建议先换成0.01度试试,等确认方法可行后再调整分辨率。
- 如果你用
linear或cubic插值,原数据覆盖范围之外的区域会自动出现缺失值,这时候可以用fill_value参数指定填充值(比如fill_value=np.nan或者一个默认常数)。 - 一定要确认原数据的经纬度范围完全覆盖你设置的规则网格范围,不然超出的部分肯定会有缺失值,这时候要么缩小规则网格的范围,要么用填充值处理。
备注:内容来源于stack exchange,提问作者Gaelle




