多元插值?
Multivariate 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])
我不知道如何处理这种插值。
在我看来,你在这里只有:
速度 = F(C) 和功率 = G(C)
因此您不需要任何多元插值,只需 interp1d
为速度创建一个函数,为功率创建另一个函数...
假设您的函数的形式为 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]
这似乎更合理。
map_coordinates
假设您在每个整数索引处都有项目,有点像在图像中。 IE。 (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'
可能对 "random" 数据具有最高保真度,但只有您可以决定哪种方法适合您的数据以及您要做什么(默认为 method='linear'
, 用于上面的 [29]
).
请注意,部分答案是 nan
。这是因为您提供的输入不在 "bounding polygon" 内,您的点在 2D space.
中形成
这是一个可视化来向您展示我的意思:
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()
我没有连接绿色的点,但是你可以看到红色的两个点在我连接这些点后形成的多边形之外。您不能在该范围之外进行插值,因此您会得到 nan
。要了解原因,请考虑一维情况。如果我问你 [0,1,2,3]
的索引 2.5 处的值是多少,一个合理的回答是 2.5
。但是,如果我问索引 100 的值是什么……我们先验地不知道 100 是什么,它远远超出了您可以看到的范围。所以我们真的无法给出答案。说它是 100
这个功能是错误的,因为那将是 extrapolation,而不是 interpolation.
HTH.
我有这样的数据。 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])
我不知道如何处理这种插值。
在我看来,你在这里只有:
速度 = F(C) 和功率 = G(C)
因此您不需要任何多元插值,只需 interp1d
为速度创建一个函数,为功率创建另一个函数...
假设您的函数的形式为 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]
这似乎更合理。
map_coordinates
假设您在每个整数索引处都有项目,有点像在图像中。 IE。 (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'
可能对 "random" 数据具有最高保真度,但只有您可以决定哪种方法适合您的数据以及您要做什么(默认为 method='linear'
, 用于上面的 [29]
).
请注意,部分答案是 nan
。这是因为您提供的输入不在 "bounding polygon" 内,您的点在 2D space.
这是一个可视化来向您展示我的意思:
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()
我没有连接绿色的点,但是你可以看到红色的两个点在我连接这些点后形成的多边形之外。您不能在该范围之外进行插值,因此您会得到 nan
。要了解原因,请考虑一维情况。如果我问你 [0,1,2,3]
的索引 2.5 处的值是多少,一个合理的回答是 2.5
。但是,如果我问索引 100 的值是什么……我们先验地不知道 100 是什么,它远远超出了您可以看到的范围。所以我们真的无法给出答案。说它是 100
这个功能是错误的,因为那将是 extrapolation,而不是 interpolation.
HTH.