Python Numpy/Scipy中大气数据的快速三维插值

Python Numpy/Scipy中大气数据的快速三维插值,python,numpy,scipy,interpolation,Python,Numpy,Scipy,Interpolation,我正在尝试使用Numpy/Scipy将三维大气数据从一个垂直坐标插值到另一个垂直坐标。例如,我有温度和相对湿度的立方体,它们都在恒定的、规则的压力表面上。我想将相对湿度插值到恒温表面 我试图解决的确切问题之前已经有人问过了,但是,那里的解决方案非常缓慢。在我的例子中,我的立方体(30x321x321)中有大约3M个点,该方法对一组数据进行操作大约需要4分钟 那个职位已经有将近5年的历史了。新版本的Numpy/Scipy是否有更快处理此问题的方法?也许新一代的眼光看待这个问题有更好的方法?我愿意接

我正在尝试使用Numpy/Scipy将三维大气数据从一个垂直坐标插值到另一个垂直坐标。例如,我有温度和相对湿度的立方体,它们都在恒定的、规则的压力表面上。我想将相对湿度插值到恒温表面

我试图解决的确切问题之前已经有人问过了,但是,那里的解决方案非常缓慢。在我的例子中,我的立方体(30x321x321)中有大约3M个点,该方法对一组数据进行操作大约需要4分钟

那个职位已经有将近5年的历史了。新版本的Numpy/Scipy是否有更快处理此问题的方法?也许新一代的眼光看待这个问题有更好的方法?我愿意接受建议

编辑:

对于一组数据立方体,慢=4分钟。我不确定我还能如何量化它

正在使用的代码

def interpLevel(grid,value,data,interp='linear'):
    """
    Interpolate 3d data to a common z coordinate.

    Can be used to calculate the wind/pv/whatsoever values for a common
    potential temperature / pressure level.

    grid : numpy.ndarray
       The grid. For example the potential temperature values for the whole 3d
       grid.

    value : float
       The common value in the grid, to which the data shall be interpolated.
       For example, 350.0

    data : numpy.ndarray
       The data which shall be interpolated. For example, the PV values for
       the whole 3d grid.

    kind : str
       This indicates which kind of interpolation will be done. It is directly
       passed on to scipy.interpolate.interp1d().

    returns : numpy.ndarray
       A 2d array containing the *data* values at *value*.

    """
    ret = np.zeros_like(data[0,:,:])
    for yIdx in xrange(grid.shape[1]):
        for xIdx in xrange(grid.shape[2]):
            # check if we need to flip the column
            if grid[0,yIdx,xIdx] > grid[-1,yIdx,xIdx]:
                ind = -1
            else:
                ind = 1
            f = interpolate.interp1d(grid[::ind,yIdx,xIdx], \
                data[::ind,yIdx,xIdx], \
                kind=interp)
            ret[yIdx,xIdx] = f(value)
    return ret
编辑2:
如果有人对我的工作感兴趣,我可以分享npy转储的样本数据。

因为这是大气数据,我想你的网格没有统一的间距;但是,如果栅格是直线的(这样每个垂直柱都具有相同的z坐标集),则可以使用一些选项

例如,如果您只需要线性插值(例如用于简单的可视化),您可以执行以下操作:

# Find nearest grid point
idx = grid[:,0,0].searchsorted(value)
upper = grid[idx,0,0]
lower = grid[idx - 1, 0, 0]
s = (value - lower) / (upper - lower)
result = (1-s) * data[idx - 1, :, :] + s * data[idx, :, :]
(当然,您需要添加
超出范围的检查)。对于您大小的网格,这将是非常快的(就像在很小的几分之一秒内)

如果需要,您可以非常轻松地修改上述内容以执行立方插值;挑战在于为不均匀的垂直间距选择正确的权重

使用scipy.ndimage.map_坐标的问题在于,尽管它提供了高阶插值并可以处理任意采样点,但它确实假设输入数据的间隔是均匀的。它仍然会产生平滑的结果,但它不是一个可靠的近似值

如果坐标网格不是直线的,因此给定索引的z值会因不同的x和y索引而改变,那么您现在使用的方法可能是您在不分析特定问题的情况下所能得到的最佳方法

更新:

一个巧妙的技巧(同样,假设每个列都有相同的,不一定是规则的坐标)是使用
interp1d
提取权重,方法如下:

NZ = grid.shape[0]
zs = grid[:,0,0]
ident = np.identity(NZ)
weight_func = interp1d(zs, ident, 'cubic')
每个网格只需执行上述操作一次;只要垂直坐标不变,您甚至可以重用weight_func

当需要插值时,
weight\u func(value)
将为您提供权重,您可以使用该权重计算
(x\u idx,y\u idx)
处的单个插值,其中:

weights = weight_func(value)
interp_val = np.dot(data[:, x_idx, y_idx), weights)
如果要计算插值的整个平面,可以使用
np.inner
,但由于z坐标位于第一位,因此需要执行以下操作:

result = np.inner(data.T, weights).T

同样,计算应该是即时的。

定义“慢”并发布您正在使用的代码。对于细节模糊的问题,很难提供有用的建议。你可以使用numpy掩码将列翻转移出双循环。类似于:
mask=grid[0,…]>grid[-1,…];grid[:,mask]=grid[::-1,mask]
(未经测试)。看一下。听起来您想要
scipy.ndimage.map\u坐标(或者可能是最近添加的
scipy.interpolate.RegularGridInterpolator
两者基本上做相同的事情)。我现在没有时间给出一个完整的答案,但是如果你的原始数据在一个常规的网格上,就没有必要使用更昂贵的方法。谢谢你的建议。随着假期的到来,我将在周一才能测试它们。这些建议,虽然非常感谢,但对我的数据不起作用。数据在所有三个维度上都是非线性和非单调变化的,因此我似乎一直在坚持在每个x,y处创建1D插值函数。如果
数据
数组不是单调或线性的,则上述技术可以正常工作,但您的意思是
网格中的值对于给定的x和y索引不是单调的吗?Hmmm-如果是这种情况,则不清楚interp1d是否合适(它用于近似单值函数,并将对其输入进行排序,以使第一个数组增加)。我可能没有很好地解释这个问题。我是一名气象学家,后来成了黑客程序员向上移动一列(网格[:,x,y]),
网格
数据
中的值将上下非线性变化。这有帮助吗?我看到的问题是,interp1d的第一个参数需要单调递增的输入,所以如果网格[:,xIdx,yIdx]不是严格递增的(可能在翻转它之后),那么从interp1d得到的结果已经有缺陷了,“在这种情况下,你不能真正使用样条插值”。