我在一个以pi
弧度包裹的域上有角度数据(即0 = pi
)。数据为2D
,其中一维代表角度。我需要以包装的方式将这些数据插入另一个网格。
在一个维度中,np.interp
函数需要一段时间kwarg
(对于NumPy
1.10及更高版本):
http://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html
这正是我所需要的,但我需要二维。我目前只是单步执行数组中的列并使用np.interp
,但这当然很慢。
那里有什么可以实现同样的结果但更快?
答案 0 :(得分:1)
np.interp
如何运作的解释使用source,Luke!
numpy doc for np.interp
使得源代码特别容易找到,因为它在那里有链接以及文档。让我们逐行了解一下。
首先,回想一下参数:
"""
x : array_like
The x-coordinates of the interpolated values.
xp : 1-D sequence of floats
The x-coordinates of the data points, must be increasing if argument
`period` is not specified. Otherwise, `xp` is internally sorted after
normalizing the periodic boundaries with ``xp = xp % period``.
fp : 1-D sequence of floats
The y-coordinates of the data points, same length as `xp`.
period : None or float, optional
A period for the x-coordinates. This parameter allows the proper
interpolation of angular x-coordinates. Parameters `left` and `right`
are ignored if `period` is specified.
"""
让我们来看一个三角波的简单例子:
xp = np.array([-np.pi/2, -np.pi/4, 0, np.pi/4])
fp = np.array([0, -1, 0, 1])
x = np.array([-np.pi/8, -5*np.pi/8]) # Peskiest points possible }:)
period = np.pi
现在,在所有类型检查发生后,我从源代码中的period != None
分支开始:
# normalizing periodic boundaries
x = x % period
xp = xp % period
这只是确保所提供的x
和xp
的所有值都在0
和period
之间。因此,由于期间为pi
,但我们指定x
和xp
介于-pi/2
和pi/2
之间,这将通过添加{{}来调整1}}到pi
范围内的所有值,以便它们有效地出现在[-pi/2, 0)
之后。因此,我们的pi/2
现在会读取xp
。
[pi/2, 3*pi/4, 0, pi/4]
这只是按递增顺序排序asort_xp = np.argsort(xp)
xp = xp[asort_xp]
fp = fp[asort_xp]
。在上一步中执行模数运算后尤其需要这样做。所以,现在xp
是xp
。 [0, pi/4, pi/2, 3*pi/4]
已经相应地改变了fp
。
[0, 1, 0, -1]
xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period))
fp = np.concatenate((fp[-1:], fp, fp[0:1]))
return compiled_interp(x, xp, fp, left, right) # Paraphrasing a little
执行线性插值。在尝试在np.interp
中的两个点a
和b
之间进行插值时,它仅使用xp
和f(a)
的值(即{的值} {1}}在相应的索引处)。那么f(b)
在最后一步中所做的是取点fp
并将其放在数组前面,取点np.interp
并将其放在数组之后,但之后分别减去和添加一个句点。因此,您现在拥有一个看起来像xp[-1]
的新xp[0]
。同样,xp
和[-pi/4, 0, pi/4, pi/2, 3*pi/4, pi]
已被连接,因此fp[0]
现在是fp[-1]
。
请注意,在模运算后,fp
也已进入[-1, 0, 1, 0, -1, 0]
范围,因此x
现在为[0, pi]
。这可以让您轻松看到自己回来x
。
假设你有一个网格和一些值。让我们把所有的值都放在[7*pi/8, 3*pi/8]
之间,这样我们就不必担心模数和混乱了。
[-0.5, 0.5]
我们现在知道您需要做的就是在数组前添加[0, pi]
,在结尾添加xp = np.array([0, np.pi/4, np.pi/2, 3*np.pi/4])
yp = np.array([0, 1, 2, 3])
period = np.pi
# Put x on the 1st dim and y on the 2nd dim; f is linear in y
fp = np.array([0, 1, 0, -1])[:, np.newaxis] + yp[np.newaxis, :]
# >>> fp
# array([[ 0, 1, 2, 3],
# [ 1, 2, 3, 4],
# [ 0, 1, 2, 3],
# [-1, 0, 1, 2]])
,调整时间段。请注意我是如何使用单例列表xp[[-1]]
和xp[[0]]
编制索引的。这是trick,以确保dimensions are preserved。
[-1]
最后,您可以自由使用scipy.interpolate.interpn
来获得结果。让我们获得所有[0]
的{{1}}值:
xp = np.concatenate((xp[[-1]]-period, xp, xp[[0]]+period))
fp = np.concatenate((fp[[-1], :], fp, fp[[0], :]))
必须将 x = pi/8
指定为Nx2点的矩阵,其中第一个维度是您希望在第二个维度处插值的每个点,给出该点的x和y坐标。有关详细说明,请参阅this answer。
如果您希望获得超出y
范围的值,您需要自己对其进行模数化:
from scipy.interpolate import interpn
interp_points = np.hstack(( (np.pi/8 * np.ones(4))[:, np.newaxis], yp[:, np.newaxis] ))
result = interpn((xp, yp), fp, interp_points)
# >>> result
# array([ 0.5, 1.5, 2.5, 3.5])
同样,如果您想为一堆x值和y值生成interp_points
,请查看this answer。