在 Python 中同时插入行
Interpolate rows simultaneously in Python
我正在尝试矢量化我的代码,但遇到了障碍。我有:
- nxd 个 x 值数组
[[x1],[...],[xn]]
(其中每一行 [x1]
有很多点 [x11, ..., x1d]
- nxd y 值数组
[[y1],[y2],[y3]]
(其中每一行 [y1]
有很多点 [y11, ..., y1d]
- nx1 个 x' 值数组
[[x'1],[...],[x'n]]
,我想根据对应的 x 和 y 行插入一个 y 值
我唯一能想到使用的是像 [np.interp(x'[i,:], x[i,:], y[i,:]) for i in range(n)]
这样的列表理解。如果存在的话,我想要一个更快的矢量化选项。感谢您的帮助!
这不是一个答案,但我想它可能对某些人仍然有用(如果没有,请随时删除);顺便说一下,
我想我一开始误解了你的问题。您拥有的是 n
个不同的一维数据集或您想要插值的函数 y(x) 的集合(否则请纠正我)。
因此,事实证明,通过多维插值来执行此操作是一种糟糕的方法。
我认为的想法是向数据添加一个新维度,以便将您的数据集映射到一个数据集中,这个新维度是区分不同 xi
,其中 i=1,2,..., n
。换句话说,您在这个新维度中为 x
的每一行分配一个值,比方说 z
;这样,不同的函数就正确映射到了这个高维的 space.
但是,这种方法比 np.interp
列表理解解决方案慢,在我的计算机中至少慢一个数量级。我想这与二维插值算法有关,最好是 O(nlog(n)) (这是一个猜测);从这个意义上说,对不同数据集执行多次插值似乎比一次大插值更有效。
无论如何,该方法显示在以下片段中:
import numpy as np
from scipy.interpolate import LinearNDInterpolator
def vectorized_interpolation(x, y, xq):
"""
Vectorized option using LinearNDInterpolator
"""
# Dummy new data points in added dimension
z = np.arange(x.shape[0])
# We must repeat every z value for every row of x
interpolant = LinearNDInterpolator(list(zip(x.ravel(), np.repeat(z, x.shape[1]))), y.ravel())
return interpolant(xq, z)
def non_vectorized_interpolation(x, y, xq):
"""
Your non-vectorized solution
"""
return np.array([np.interp(xq[i], x[i], y[i]) for i in range(x.shape[0])])
if __name__ == "__main__":
n, d = 100, 500
x = np.linspace(0, 2*np.pi, n*d).reshape((n, d))
y = np.sin(x)
xq = np.linspace(0, 2*np.pi, n)
yq1 = vectorized_interpolation(x, y, xq)
yq2 = non_vectorized_interpolation(x, y, xq)
矢量化解决方案的唯一优点是 LinearNDInterpolator
(以及其他一些 scipy.interpolate
函数)显式计算插值,因此如果您计划对相同的数据集进行插值,则可以重用它多次,避免重复计算。如果您的机器中有多个内核,您可以尝试的另一件事是使用多处理,但这不是您要求的矢量化。抱歉,我帮不上忙了。
我正在尝试矢量化我的代码,但遇到了障碍。我有:
- nxd 个 x 值数组
[[x1],[...],[xn]]
(其中每一行[x1]
有很多点[x11, ..., x1d]
- nxd y 值数组
[[y1],[y2],[y3]]
(其中每一行[y1]
有很多点[y11, ..., y1d]
- nx1 个 x' 值数组
[[x'1],[...],[x'n]]
,我想根据对应的 x 和 y 行插入一个 y 值
我唯一能想到使用的是像 [np.interp(x'[i,:], x[i,:], y[i,:]) for i in range(n)]
这样的列表理解。如果存在的话,我想要一个更快的矢量化选项。感谢您的帮助!
这不是一个答案,但我想它可能对某些人仍然有用(如果没有,请随时删除);顺便说一下,
我想我一开始误解了你的问题。您拥有的是 n
个不同的一维数据集或您想要插值的函数 y(x) 的集合(否则请纠正我)。
因此,事实证明,通过多维插值来执行此操作是一种糟糕的方法。
我认为的想法是向数据添加一个新维度,以便将您的数据集映射到一个数据集中,这个新维度是区分不同 xi
,其中 i=1,2,..., n
。换句话说,您在这个新维度中为 x
的每一行分配一个值,比方说 z
;这样,不同的函数就正确映射到了这个高维的 space.
但是,这种方法比 np.interp
列表理解解决方案慢,在我的计算机中至少慢一个数量级。我想这与二维插值算法有关,最好是 O(nlog(n)) (这是一个猜测);从这个意义上说,对不同数据集执行多次插值似乎比一次大插值更有效。
无论如何,该方法显示在以下片段中:
import numpy as np
from scipy.interpolate import LinearNDInterpolator
def vectorized_interpolation(x, y, xq):
"""
Vectorized option using LinearNDInterpolator
"""
# Dummy new data points in added dimension
z = np.arange(x.shape[0])
# We must repeat every z value for every row of x
interpolant = LinearNDInterpolator(list(zip(x.ravel(), np.repeat(z, x.shape[1]))), y.ravel())
return interpolant(xq, z)
def non_vectorized_interpolation(x, y, xq):
"""
Your non-vectorized solution
"""
return np.array([np.interp(xq[i], x[i], y[i]) for i in range(x.shape[0])])
if __name__ == "__main__":
n, d = 100, 500
x = np.linspace(0, 2*np.pi, n*d).reshape((n, d))
y = np.sin(x)
xq = np.linspace(0, 2*np.pi, n)
yq1 = vectorized_interpolation(x, y, xq)
yq2 = non_vectorized_interpolation(x, y, xq)
矢量化解决方案的唯一优点是 LinearNDInterpolator
(以及其他一些 scipy.interpolate
函数)显式计算插值,因此如果您计划对相同的数据集进行插值,则可以重用它多次,避免重复计算。如果您的机器中有多个内核,您可以尝试的另一件事是使用多处理,但这不是您要求的矢量化。抱歉,我帮不上忙了。