我有两个相同长度的1D阵列,包含时间序列和值系列,例如
t = linspace(0, 5, 5) # [0, 1.25, 2.5, 3.75, 5]
x = array(range(10, 25)) # [10, 11, 12, 13, 14]
我必须使用不同的采样点及时重新采样x数组(具有相同的起点和终点,但可以包含任意数量的元素),例如
r = linspace(0, 5, 4) # [ 0, 1.667, 3.333, 5]
x2 = resample(t, x, r) # [10, 11, 12, 14]
也就是说,r的每个时间点都放在t的两个时间点之间,我想在t中找到两个较低点的索引。从索引数组中,可以获得x的相对点。
我想要一个基于矢量的解决方案,没有循环,可能使用scipy的运算符。 如果使用scipy的函数会更好。
编辑:这是一个能够满足我需要的代码,但更短,更快,基于矢量的解决方案会更好。我找不到一个(直到尝试)。def resample(t, r):
i, j, k = 0, 1, 0
s = []
while j < len(t):
if t[i] <= r[k] < t[j]:
s.append(i)
k += 1
else:
i += 1
j += 1
s.append(len(t) - 1)
return array(s)
答案 0 :(得分:1)
您可以尝试使用interp1d
中的scipy.interpolate
功能,将kind
参数指定为zero
。使用你的数组:
>>> from scipy.interpolate import interp1d
>>> f = interp1d(t,x,kind="zero")
>>> f(r)
array((10, 11, 12, 13))
请注意,“resampled”数组中的最后一个元素是13,而不是您在问题中请求的14,而是f(5.001) = 14
(*)。只要“重采样”数组与原始数组中的一个点匹配,插值函数就是不连续的。
(*)如果要在bounds_error=False
范围之外重新取样,则需要在interp1d
调用中指定关键字参数t
。
答案 1 :(得分:1)
以下两个小函数中的第二个可以得到你想要的东西:
def resample_up(t, x, r) :
return x[np.argmax(r[:, None] <= t, axis=1)]
def resample_down(t, x, r) :
return x[::-1][np.argmax(r[:, None] >= t[::-1], axis=1)]
>>> resample_up(t, x, r)
array([10, 12, 13, 14])
>>> resample_down(t, x, r)
array([10, 11, 12, 14])
如果您发现很难弄清楚发生了什么,以下内容可能有所帮助:
>>> r[:, None] <= t
array([[ True, True, True, True, True],
[False, False, True, True, True],
[False, False, False, True, True],
[False, False, False, False, True]], dtype=bool)
>>> r[:, None] >= t[::-1]
array([[False, False, False, False, True],
[False, False, False, True, True],
[False, False, True, True, True],
[ True, True, True, True, True]], dtype=bool)
然后np.argmax
返回每行中第一次出现True
的索引。
编辑 IT很难让它比单行代码更短,但对于大型数组,性能会受到影响,因为索引查找从未在循环的早期发生。因此对于非常大的数组,使用python循环扫描数组可能会更快。对于较小的那些,它不会:
In [2]: %timeit resample_up(t, x, r)
100000 loops, best of 3: 7.32 us per loop
In [3]: %timeit resample_down(t, x, r)
100000 loops, best of 3: 8.44 us per loop
In [4]: %timeit resample(t, x, r) # modified version of the OP's taking also x
100000 loops, best of 3: 13.7 us per loop
答案 2 :(得分:1)
numpy.interp是一个快速简单的分段线性插值器:
from __future__ import division
import numpy as np
t = np.linspace(0, 5, 5) # [0, 1.25, 2.5, 3.75, 5]
x = np.array(range(10, 15)) # [10, 11, 12, 13, 14]
r = np.linspace(0, 5, 4) # [ 0, 1.667, 3.333, 5]
print "np.interp:", np.interp( r, t, x )
# [ 10. 11.33 12.67 14. ]
xint = np.arange( len(t) )
print "r to int:", np.interp( r, t, xint ).astype(int)
# [0 1 2 4]