底图插值替代方案 - 重新网格化数据

Basemap interpolation alternative - regridding data

鉴于底图将被淘汰,我正在从底图转向 cartopy。我以前使用 basemap.interp 功能来插入数据,例如假设我有 1 度分辨率 (180x360) 的数据,我将 运行 以下内容插值到 0.5 度。

import numpy as np
from mpl_toolkits import basemap

Old_Lon = np.linspace(-180,180,360)
Old_Lat = np.linspace(-90,90,180)
New_Lon = np.linspace(-180,180,720)
New_Lat = np.linspace(-90,90,360)

New_Lon,New_Lat = np.meshgrid(New_Lon,New_Lat)

New_Data = basemap.interp(Old_Data,Old_Lon,Old_Lat,New_Lon,New_Lat,order=0)

order 让我可以从最近的邻居、双线性等中进行选择。是否有一种替代方法可以以如此简单的方式做到这一点?我看到 scipy 有插值,但我不确定如何应用它。如有任何帮助,我们将不胜感激!

SciPy 插值例程 return 可以调用以执行插值的函数。对于规则网格上的最近邻插值,可以使用 scipy.interpolate.RegularGridInterpolator:

import numpy as np
from scipy.interpolate import RegularGridInterpolator

nearest_function = RegularGridInterpolator(
    (old_lon, old_lat), old_data, method="nearest", bounds_error=False
)

new_data = np.array(
    [[nearest_function([i, j]) for j in new_lat] for i in new_lon]
).squeeze()

但这并不完美,因为 lon=175 都是填充值。 (如果我没有设置 bounds_error=False 那么你会在那里得到一个错误。)在那种情况下,你需要询问你想如何环绕日期线。一个直接的解决方案是将 lon=0 行复制到数组的末尾并将其命名为 lon=180.

如果有一天你想要线性或高阶插值,如果你的数据是点而不是单元格,我建议你这样做,你可以使用 scipy.interpolate.RectBivariateSpline:

import numpy as np
from scipy.interpolate import RectBivariateSpline

old_step = 10
old_lon = np.arange(-180, 180, old_step)
old_lat = np.arange(-90, 90, old_step)
old_data = np.random.random((len(old_lon), len(old_lat)))
interp_function = RectBivariateSpline(old_lon, old_lat, old_data, kx=1, ky=1)

new_lon = np.arange(-180, 180, new_step)
new_lat = np.arange(-90, 90, new_step)
new_data = interp_function(new_lon, new_lat)

我最终决定从 Basemap 中获取原始代码并将其变成一个独立的函数 - 我将把它推荐给 cartopy 的人来实现它作为一个有用的功能。在这里发帖可能对其他人有用:

def Interp(datain,xin,yin,xout,yout,interpolation='NearestNeighbour'):

    """
       Interpolates a 2D array onto a new grid (only works for linear grids), 
       with the Lat/Lon inputs of the old and new grid. Can perfom nearest
       neighbour interpolation or bilinear interpolation (of order 1)'

       This is an extract from the basemap module (truncated)
    """

    # Mesh Coordinates so that they are both 2D arrays
    xout,yout = np.meshgrid(xout,yout)

   # compute grid coordinates of output grid.
    delx = xin[1:]-xin[0:-1]
    dely = yin[1:]-yin[0:-1]

    xcoords = (len(xin)-1)*(xout-xin[0])/(xin[-1]-xin[0])
    ycoords = (len(yin)-1)*(yout-yin[0])/(yin[-1]-yin[0])


    xcoords = np.clip(xcoords,0,len(xin)-1)
    ycoords = np.clip(ycoords,0,len(yin)-1)

    # Interpolate to output grid using nearest neighbour
    if interpolation == 'NearestNeighbour':
        xcoordsi = np.around(xcoords).astype(np.int32)
        ycoordsi = np.around(ycoords).astype(np.int32)
        dataout = datain[ycoordsi,xcoordsi]

    # Interpolate to output grid using bilinear interpolation.
    elif interpolation == 'Bilinear':
        xi = xcoords.astype(np.int32)
        yi = ycoords.astype(np.int32)
        xip1 = xi+1
        yip1 = yi+1
        xip1 = np.clip(xip1,0,len(xin)-1)
        yip1 = np.clip(yip1,0,len(yin)-1)
        delx = xcoords-xi.astype(np.float32)
        dely = ycoords-yi.astype(np.float32)
        dataout = (1.-delx)*(1.-dely)*datain[yi,xi] + \
                  delx*dely*datain[yip1,xip1] + \
                  (1.-delx)*dely*datain[yip1,xi] + \
                  delx*(1.-dely)*datain[yi,xip1]

    return dataout

--