矩形网格上的 Python 4D 线性插值

标签 python numpy scipy interpolation

我需要在 4 个维度(纬度、经度、高度和时间)中线性插入温度数据。
点数相当多 (360x720x50x8),我需要一种快速方法来计算数据范围内空间和时间上任意点的温度。

我尝试过使用 scipy.interpolate.LinearNDInterpolator 但是使用 Qhull 进行三角剖分在矩形网格上效率低下并且需要数小时才能完成。

通过阅读此 SciPy ticket ,解决方案似乎是使用标准 interp1d 实现新的 nd 插值器来计算更多的数据点,然后对新数据集使用“最近邻”方法。

然而,这又需要很长时间(几分钟)。

是否有一种快速的方法可以在 4 个维度的矩形网格上插入数据而不需要几分钟才能完成?

我想过使用interp1d 4次而不计算更高密度的点,而是留给用户用坐标调用,但我无法得到我在思考如何做到这一点。

否则,可以选择根据我的需要编写我自己的 4D 插值器吗?

这是我用来测试这个的代码:

使用scipy.interpolate.LinearNDInterpolator:

import numpy as np
from scipy.interpolate import LinearNDInterpolator

lats = np.arange(-90,90.5,0.5)
lons = np.arange(-180,180,0.5)
alts = np.arange(1,1000,21.717)
time = np.arange(8)
data = np.random.rand(len(lats)*len(lons)*len(alts)*len(time)).reshape((len(lats),len(lons),len(alts),len(time)))

coords = np.zeros((len(lats),len(lons),len(alts),len(time),4))
coords[...,0] = lats.reshape((len(lats),1,1,1))
coords[...,1] = lons.reshape((1,len(lons),1,1))
coords[...,2] = alts.reshape((1,1,len(alts),1))
coords[...,3] = time.reshape((1,1,1,len(time)))
coords = coords.reshape((data.size,4))

interpolatedData = LinearNDInterpolator(coords,data)

使用scipy.interpolate.interp1d:

import numpy as np
from scipy.interpolate import LinearNDInterpolator

lats = np.arange(-90,90.5,0.5)
lons = np.arange(-180,180,0.5)
alts = np.arange(1,1000,21.717)
time = np.arange(8)
data = np.random.rand(len(lats)*len(lons)*len(alts)*len(time)).reshape((len(lats),len(lons),len(alts),len(time)))

interpolatedData = np.array([None, None, None, None])
interpolatedData[0] = interp1d(lats,data,axis=0)
interpolatedData[1] = interp1d(lons,data,axis=1)
interpolatedData[2] = interp1d(alts,data,axis=2)
interpolatedData[3] = interp1d(time,data,axis=3)

非常感谢您的帮助!

最佳答案

在您链接的同一张票中,有一个他们称之为张量乘积插值的示例实现,展示了嵌套递归调用 interp1d 的正确方法。如果您为 interp1d 选择默认的 kind='linear' 参数,这相当于四线插值。

虽然这可能已经足够好了,但这不是线性插值,插值函数中会有高阶项,因为这张图片来自 wikipedia entry on bilinear interpolation显示:

enter image description here

这可能足以满足您的需求,但在某些应用程序中,三角剖分、真正的分段线性插值是首选。如果您真的需要它,有一种简单的方法可以解决 qhull 的缓慢问题。

设置好 LinearNDInterpolator 后,有两个步骤可以为给定点得出一个插值:

  1. 找出点在哪个三角形(在你的例子中是 4D 超四面体)内,并且
  2. 使用 barycentric coordinates 进行插值点相对于顶点的权重。

您可能不想弄乱重心坐标,所以最好将其留给 LinearNDInterpolator。但是你确实知道一些关于三角测量的事情。大多数情况下,因为你有一个规则的网格,所以在每个超立方体中,三角剖分将是相同的。因此,要插入单个值,您可以首先确定您的点在哪个子立方体中,使用该立方体的 16 个顶点构建一个 LinearNDInterpolator,并使用它来插入您的值:

from itertools import product

def interpolator(coords, data, point) :
    dims = len(point)
    indices = []
    sub_coords = []
    for j in xrange(dims) :
        idx = np.digitize([point[j]], coords[j])[0]
        indices += [[idx - 1, idx]]
        sub_coords += [coords[j][indices[-1]]]
    indices = np.array([j for j in product(*indices)])
    sub_coords = np.array([j for j in product(*sub_coords)])
    sub_data = data[list(np.swapaxes(indices, 0, 1))]
    li = LinearNDInterpolator(sub_coords, sub_data)
    return li([point])[0]

>>> point = np.array([12.3,-4.2, 500.5, 2.5])
>>> interpolator((lats, lons, alts, time), data, point)
0.386082399091

这不适用于矢量化数据,因为这需要为每个可能的子立方体存储一个 LinearNDInterpolator,即使它可能比对整个事物进行三角剖分更快,但它仍然会非常慢。

关于矩形网格上的 Python 4D 线性插值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14119892/

相关文章:

Python 对 Windows 8 的支持

python - 在 Numpy 中创建 cos 和 sin 数组的最有效方法

python - 欠定系统的非负最小二乘法

Python affine_transform 不翻译?

python - 基于元素的 n 个连续实例对 pandas df 进行切片

python - 如何在 keras 中计算接收操作特征 (ROC) 和 AUC?

python - Jupyter notebook 不连接内核(2) - conda + mc os 11.5 + appnope

python - 如何从 3d numpy 数组中提取向量?

python - Power BI Rest API 请求未按预期授权

Python 字典中数组的交集