You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Windows环境下无法使用Xesmf时,如何将Xarray中的旋转网格数据插值到规则经纬度网格

Windows环境下无法使用Xesmf时,如何将Xarray中的旋转网格数据插值到规则经纬度网格

我太懂你在Windows上没法用xesmf的憋屈了!之前处理旋转网格数据时也碰到过一模一样的问题,给你几个不用xesmf也能搞定的方案,亲测在Windows上完全可行:

先说说你之前操作的问题所在

旋转网格的数据集里,latitudelongitude一般是二维变量(和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(适合原数据有一维旋转坐标的情况)

如果你的原数据集有xy这类一维的旋转网格坐标(比如笛卡尔坐标),可以先把经纬度作为xy的二维坐标,然后用规则网格模板来插值:

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度试试,等确认方法可行后再调整分辨率。
  • 如果你用linearcubic插值,原数据覆盖范围之外的区域会自动出现缺失值,这时候可以用fill_value参数指定填充值(比如fill_value=np.nan或者一个默认常数)。
  • 一定要确认原数据的经纬度范围完全覆盖你设置的规则网格范围,不然超出的部分肯定会有缺失值,这时候要么缩小规则网格的范围,要么用填充值处理。

备注:内容来源于stack exchange,提问作者Gaelle

火山引擎 最新活动