20

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

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

通过阅读此SciPy 票证,该解决方案似乎正在实施一个新的 nd 插值器,使用该标准interp1d来计算更多数量的数据点,然后对新数据集使用“最近邻”方法。

但是,这又需要很长时间(几分钟)。

有没有一种快速的方法可以在 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)

非常感谢您的帮助!

4

4 回答 4

13

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

虽然这可能已经足够好了,但这不是线性插值,并且插值函数中会有更高阶项,正如来自维基百科双线性插值条目的这张图片所示:

在此处输入图像描述

这对于您所追求的可能已经足够好了,但是在某些应用程序中,三角化、真正分段线性的插值是首选。如果你真的需要这个,有一种简单的方法可以解决 qhull 的缓慢问题。

设置完成后,有LinearNDInterpolator两个步骤可以得出给定点的插值:

  1. 找出点在哪个三角形(在您的情况下为 4D 超四面体),并且
  2. 使用点相对于顶点的重心坐标作为权重进行插值。

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

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为每个可能的子立方体存储一个,即使它可能比对整个事物进行三角剖分要快,但它仍然会非常慢。

于 2013-01-02T12:58:03.527 回答
5

scipy.ndimage.map_coordinates 是一个很好的用于均匀网格的快速插值器(所有框大小相同)。请参阅SO 上的 multivariate-spline-interpolation-in-python-scipy以获得清晰的描述。

对于非均匀的矩形网格,一个简单的包装器 Intergrid将非均匀的网格映射/缩放到均匀的网格,然后执行 map_coordinates。在像您这样的 4d 测试用例中,每个查询大约需要 1 微秒:

Intergrid: 1000000 points in a (361, 720, 47, 8) grid took 652 msec
于 2013-01-21T15:46:12.410 回答
2

对于非常相似的事情,我使用Scientific.Functions.Interpolation.InterpolatingFunction

    import numpy as np
    from Scientific.Functions.Interpolation import InterpolatingFunction

    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)))

    axes = (lats, lons, alts, time)
    f = InterpolatingFunction(axes, data)

您现在可以将其留给用户InterpolatingFunction使用坐标调用:

>>> f(0,0,10,3)
0.7085675631375401

InterpolatingFunction具有很好的附加功能,例如集成和切片。

但是,我不确定插值是否是线性的。您必须查看模块源代码才能找到答案。

于 2013-07-19T15:07:59.603 回答
0

我无法打开这个地址,并找到关于这个包裹的足够信息

于 2020-05-11T14:49:22.133 回答