NumPy:如何计算多轴上的分段线性插值
给定以下数据列NumPy:如何计算多轴上的分段线性插值,numpy,linear-interpolation,Numpy,Linear Interpolation,给定以下数据列t- In [26]: t.shape Out[26]: (3, 3, 2) In [27]: t Out[27]: array(
t
-
In [26]: t.shape
Out[26]: (3, 3, 2)
In [27]: t
Out[27]:
array([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]]])
点t[:,0,0]
的分段线性插值可以使用以下公式计算[0,0.666667,1.33333333,2.]
-
对于fp
-
array([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 4, 5],
[ 6, 7],
[ 8, 9]],
[[ 8, 9],
[10, 11],
[12, 13]],
[[12, 13],
[14, 15],
[16, 17]]])
您可以尝试
scipy.interpolate.interp1d
:
from scipy.interpolate import interp1d
import numpy as np
t = np.array([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]]])
# for the first slice
f = interp1d(np.arange(t.shape[0]), t[..., 0], axis=0)
# returns a function which you call with values within range np.arange(t.shape[0])
# data used for interpolation
t[..., 0]
>>> array([[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]])
f(1)
>>> array([ 6., 8., 10.])
f(1.5)
>>> array([ 9., 11., 13.])
您可以尝试
scipy.interpolate.interp1d
:
from scipy.interpolate import interp1d
import numpy as np
t = np.array([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]]])
# for the first slice
f = interp1d(np.arange(t.shape[0]), t[..., 0], axis=0)
# returns a function which you call with values within range np.arange(t.shape[0])
# data used for interpolation
t[..., 0]
>>> array([[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]])
f(1)
>>> array([ 6., 8., 10.])
f(1.5)
>>> array([ 9., 11., 13.])
由于插值是1d的,随着
y
值的变化,必须为t的每个1d切片运行插值。显式循环可能更快,但使用np.apply_沿_轴循环更整洁
import numpy as np
t = np.arange( 18 ).reshape(3,3,2)
x = np.linspace( 0, t.shape[0]-1, 4)
xp = np.arange(t.shape[0])
def interfunc( arr ):
""" Function interpolates a 1d array. """
return np.interp( x, xp, arr )
np.apply_along_axis( interfunc, 0, t ) # apply function along axis 0
""" Result
array([[[ 0., 1.],
[ 2., 3.],
[ 4., 5.]],
[[ 4., 5.],
[ 6., 7.],
[ 8., 9.]],
[[ 8., 9.],
[10., 11.],
[12., 13.]],
[[12., 13.],
[14., 15.],
[16., 17.]]]) """
使用显式循环
result = np.zeros((4,3,2))
for c in range(t.shape[1]):
for p in range(t.shape[2]):
result[:,c,p] = np.interp( x, xp, t[:,c,p])
在我的机器上,第二个选项在一半的时间内运行
编辑以使用np.nditer
由于结果和参数具有不同的形状,我似乎必须创建两个np.nditer对象,一个用于参数,一个用于结果。这是我第一次尝试将nditer
用于任何可能过于复杂的事情
def test( t ):
ts = t.shape
result = np.zeros((ts[0]+1,ts[1],ts[2]))
param = np.nditer( [t], ['external_loop'], ['readonly'], order = 'F')
with np.nditer( [result], ['external_loop'], ['writeonly'], order = 'F') as res:
for p, r in zip( param, res ):
r[:] = interfunc(p)
return result
它比显式循环稍慢,并且比其他任何一种解决方案都不容易遵循。由于插值是1d,随着
y
值的变化,它必须针对t的每个1d切片运行。显式循环可能更快,但使用np.apply_沿_轴循环更整洁
import numpy as np
t = np.arange( 18 ).reshape(3,3,2)
x = np.linspace( 0, t.shape[0]-1, 4)
xp = np.arange(t.shape[0])
def interfunc( arr ):
""" Function interpolates a 1d array. """
return np.interp( x, xp, arr )
np.apply_along_axis( interfunc, 0, t ) # apply function along axis 0
""" Result
array([[[ 0., 1.],
[ 2., 3.],
[ 4., 5.]],
[[ 4., 5.],
[ 6., 7.],
[ 8., 9.]],
[[ 8., 9.],
[10., 11.],
[12., 13.]],
[[12., 13.],
[14., 15.],
[16., 17.]]]) """
使用显式循环
result = np.zeros((4,3,2))
for c in range(t.shape[1]):
for p in range(t.shape[2]):
result[:,c,p] = np.interp( x, xp, t[:,c,p])
在我的机器上,第二个选项在一半的时间内运行
编辑以使用np.nditer
由于结果和参数具有不同的形状,我似乎必须创建两个np.nditer对象,一个用于参数,一个用于结果。这是我第一次尝试将nditer
用于任何可能过于复杂的事情
def test( t ):
ts = t.shape
result = np.zeros((ts[0]+1,ts[1],ts[2]))
param = np.nditer( [t], ['external_loop'], ['readonly'], order = 'F')
with np.nditer( [result], ['external_loop'], ['writeonly'], order = 'F') as res:
for p, r in zip( param, res ):
r[:] = interfunc(p)
return result
它比显式循环稍慢,而且比其他任何一种解决方案都不容易遵循。根据@Tis Chris的要求,这里有一个使用
np.nditer
和multi_index
标志的解决方案,但我更喜欢显式嵌套for
循环方法,因为它比上面的方法快10%
In [29]: t = np.arange( 18 ).reshape(3,3,2)
In [30]: ax0old = np.arange(t.shape[0])
In [31]: ax0new = np.linspace(0, t.shape[0]-1, 4)
In [32]: tnew = np.zeros((len(ax0new), t.shape[1], t.shape[2]))
In [33]: it = np.nditer(t[0], flags=['multi_index'])
In [34]: for _ in it:
...: tnew[:, it.multi_index[0], it.multi_index[1]] = np.interp(ax0new, ax0old, t[:, it.multi_
...: index[0], it.multi_index[1]])
...:
In [35]: tnew
Out[35]:
array([[[ 0., 1.],
[ 2., 3.],
[ 4., 5.]],
[[ 4., 5.],
[ 6., 7.],
[ 8., 9.]],
[[ 8., 9.],
[10., 11.],
[12., 13.]],
[[12., 13.],
[14., 15.],
[16., 17.]]])
根据@Tis Chris的要求,这里有一个使用
np.nditer
和multi_index
标志的解决方案,但我更喜欢上面的显式嵌套for
循环方法,因为它比以前快10%
In [29]: t = np.arange( 18 ).reshape(3,3,2)
In [30]: ax0old = np.arange(t.shape[0])
In [31]: ax0new = np.linspace(0, t.shape[0]-1, 4)
In [32]: tnew = np.zeros((len(ax0new), t.shape[1], t.shape[2]))
In [33]: it = np.nditer(t[0], flags=['multi_index'])
In [34]: for _ in it:
...: tnew[:, it.multi_index[0], it.multi_index[1]] = np.interp(ax0new, ax0old, t[:, it.multi_
...: index[0], it.multi_index[1]])
...:
In [35]: tnew
Out[35]:
array([[[ 0., 1.],
[ 2., 3.],
[ 4., 5.]],
[[ 4., 5.],
[ 6., 7.],
[ 8., 9.]],
[[ 8., 9.],
[10., 11.],
[12., 13.]],
[[12., 13.],
[14., 15.],
[16., 17.]]])
@我注意到您使用标准python循环技术来迭代
t
的第二和第三轴。使用numpy.nditer
有什么好处吗?@user2309803我花了一些时间来试验nditer
。由于文档的长度,我避免了它:-)这个解决方案似乎比其他任何一个都笨拙,但是对于这里的数据来说,运行速度比显式循环稍微慢一点。我不确定在这种情况下,nditer
是否有任何好处。也许我的实现中遗漏了一些东西。@Tis Chris:我设法使用np.nditer(t[0],flags=['multi_index'])重新实现了您的解决方案。
但是速度慢了10%。@user2309803:您能作为解决方案发布吗。我从来没有真正尝试过去理解nditer,也没有发现过我认为它能解决的问题。我注意到您使用标准的python循环技术在t
的第二和第三轴上进行迭代。使用numpy.nditer
有什么好处吗?@user2309803我花了一些时间来试验nditer
。由于文档的长度,我避免了它:-)这个解决方案似乎比其他任何一个都笨拙,但是对于这里的数据来说,运行速度比显式循环稍微慢一点。我不确定在这种情况下,nditer
是否有任何好处。也许我的实现中遗漏了一些东西。@Tis Chris:我设法使用np.nditer(t[0],flags=['multi_index'])重新实现了您的解决方案。
但是速度慢了10%。@user2309803:您能作为解决方案发布吗。我从来没有真正尝试过去理解nditer,也没有发现过我认为它能解决的问题。很高兴见到你。谢谢。我现在更清楚这是怎么回事了。我有代码可以沿源数组的任意选定轴执行插值。我想知道nditer是否可以加快速度或让它更清晰,谢谢。我现在更清楚这是怎么回事了。我有代码可以沿源数组的任意选定轴执行插值。我想知道nditer能不能加快速度或者让它更清晰,