【问题标题】:Basemap interpolation alternative - regridding data底图插值替代方案 - 重新网格化数据
【发布时间】:2018-02-23 10:25:40
【问题描述】:

鉴于底图将被逐步淘汰,我正在从底图转移到 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 有插值,但我不知道如何应用它。任何帮助将不胜感激!

【问题讨论】:

    标签: python numpy matplotlib interpolation matplotlib-basemap


    【解决方案1】:

    我最终决定从 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
    

    --

    【讨论】:

      【解决方案2】:

      SciPy 插值例程返回一个函数,您可以调用该函数来执行插值。对于规则网格上的最近邻插值,您可以使用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)
      

      【讨论】:

      • 这是一个非常好的答案,谢谢。我对最近邻居的唯一关心是运行 vs basemap.interp 函数所需的时间长度。
      • 我通过从源代码中复制 basemap.interp 函数并将其变成一个独立函数来解决这个问题。谢谢!
      • 在大多数情况下,我希望地图创建比插值花费更长的时间,但我从来没有花时间学习 Basemap。此外,如果您认为它很有用,您可以要求 Cartopy 复制此例程。马克相当友好:)
      猜你喜欢
      • 2013-03-26
      • 2011-01-08
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 2016-10-14
      • 2017-09-21
      • 2010-10-02
      相关资源
      最近更新 更多