多元插值?

时间:2018-11-21 19:45:09

标签: python numpy scipy interpolation

我有这种数据。 x轴速度和y轴功率。这给出了一个情节。但是,有很多C值可以在速度与功率关系图上给出其他曲线图。

数据为:

C = 12
speed:[127.1, 132.3, 154.3, 171.1, 190.7, 195.3]
power:[2800, 3400.23, 5000.1, 6880.7, 9711.1, 10011.2 ]

C = 14
speed:[113.1, 125.3, 133.3, 155.1, 187.7, 197.3]
power:[2420, 3320, 4129.91, 6287.17, 10800.34, 13076.5 ]

现在,我希望能够在[[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]]处进行插值。

我已阅读this的答案。我不确定这是否是这样做的方式。

我尝试过:

data = np.array([[12, 127.1, 2800], [12, 132.3, 3400.23], [12, 154.3, 5000.1], [12, 171.1, 6880.7],
                [12, 190.7, 9711.1], [12, 195.3, 10011.2],
                [14, 113.1, 2420], [14, 125.3, 3320], [14, 133.3, 4129.91], [14, 155.1, 6287.17],
                [14, 187.7, 10800.34], [14, 197.3, 13076.5]])

coords = np.array([[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]])

z = ndimage.map_coordinates(data, coords.T, order=2, mode='nearest')

但是,我收到了:

array([13076.5, 13076.5, 13076.5, 13076.5, 13076.5, 13076.5])

我不确定如何处理这种插值。

3 个答案:

答案 0 :(得分:2)

map_coordinates假设您在每个整数索引处都有项目,就像在图像中那样。即(0,0),(0,1)...,(0,100),(1,0),(1,1),...,(100,0),(100,1),。 ..,(100,100)是所有坐标,如果您具有100x100的图像,则坐标定义明确。这不是你的情况。您的数据位于坐标(12,127.1),(12,132.3)等处。

您可以改用griddata。根据您想要进行插值的方式,您将获得不同的结果:

In [24]: data = np.array([[12, 127.1, 2800], [12, 132.3, 3400.23], [12, 154.3, 5000.1], [12, 171.1, 6880.7],
    ...:                 [12, 190.7, 9711.1], [12, 195.3, 10011.2],
    ...:                 [14, 113.1, 2420], [14, 125.3, 3320], [14, 133.3, 4129.91], [14, 155.1, 6287.17],
    ...:                 [14, 187.7, 10800.34], [14, 197.3, 13076.5]])

In [25]: from scipy.interpolate import griddata

In [28]: coords = np.array([[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]])

In [29]: griddata(data[:, 0:2], data[:, -1], coords)
Out[29]:
array([           nan,  3895.22854545,  5366.64369048,  7408.68906748,
       10791.779     ,            nan])

In [31]: griddata(data[:, 0:2], data[:, -1], coords, method='nearest')
Out[31]: array([ 3320.  ,  4129.91,  5000.1 ,  6880.7 ,  9711.1 , 13076.5 ])

In [32]: griddata(data[:, 0:2], data[:, -1], coords, method='cubic')
Out[32]:
array([           nan,  3998.75479082,  5357.54672326,  7297.94115979,
       10647.04183455,            nan])

method='cubic'可能对“随机”数据具有最高的保真度,但是只有您可以决定哪种方法适合您的数据以及您要执行的操作(默认为method='linear',用于[29])。

请注意,某些答案是nan。这是因为您提供的输入不在点在2D空间中形成的“边界多边形”之内。

以下是可视化内容,向您展示我的意思:

In [49]: x = plt.scatter(x=np.append(data[:, 0], [12.2, 12.8]), y=np.append(data[:, 1], [122.1, 198.5]), c=['green']*len(data[:, 0]) + ['red']*2)

In [50]: plt.show()

bounding polygon

我没有用绿色连接这些点,但是您可以看到红色的两个点在如果我将这些点连接在一起将形成的多边形之外。您无法在该范围之外进行插值,因此得到nan。要了解原因,请考虑一维情况。如果我问你[0,1,2,3]的索引2.5处的值是多少,那么合理的答案应该是2.5。但是,如果我问索引100的值是什么...先验,我们不知道索引100的值是什么,那么它超出了您所看到的范围。因此,我们无法真正给出答案。说100对于此功能是错误的,因为那将是外推,而不是内插

HTH。

答案 1 :(得分:1)

假设函数的形式为power = F(C,speed),则可以使用scipy.interpolate.interp2d

import scipy.interpolate as sci

speed = [127.1, 132.3, 154.3, 171.1, 190.7, 195.3]
C = [12]*len(speed)
power = [2800, 3400.23, 5000.1, 6880.7, 9711.1, 10011.2 ]

speed += [113.1, 125.3, 133.3, 155.1, 187.7, 197.3]
C += [14]*(len(speed) - len(C))
power += [2420, 3320, 4129.91, 6287.17, 10800.34, 13076.5 ]

f = sci.interp2d(C, speed, power)

coords = np.array([[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]])
power_interp = np.concatenate([f(*coord) for coord in coords])

with np.printoptions(precision=1, suppress=True, linewidth=9999):
    print(power_interp)

这将输出:

[1632.4 2659.5 3293.4 4060.2 5074.8 4506.6]

似乎有点低。原因是interp2d默认使用线性样条拟合,并且您的数据肯定是非线性的。通过LSQBivariateSpline直接访问样条拟合例程,可以获得更好的结果:

xknots = (min(C), max(C))
yknots = (min(speed), max(speed))
f = sci.LSQBivariateSpline(C, speed, power, tx=xknots, ty=yknots, kx=2, ky=3)

power_interp = f(*coords.T, grid=False)

with np.printoptions(precision=1, suppress=True, linewidth=9999):
    print(power_interp)

这将输出:

[ 2753.2  3780.8  5464.5  7505.2 10705.9 11819.6]

这似乎更合理。

答案 2 :(得分:0)

在我看来,您所拥有的只是:

速度= F(C)和功率= G(C)

因此您不需要任何多元插值,只需interp1d即可创建一个函数来实现速度,而另一个函数来实现幂...