1

例如,我有两个长度相同的一维数组,包含时间序列和值序列

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)
4

3 回答 3

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

编辑它很难让它比一行代码更短,但是对于大型数组,性能会受到影响,因为索引查找永远不会在循环的早期中断。因此,对于非常大的数组,使用 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
于 2013-01-30T23:55:58.327 回答
1

您可以尝试使用interp1din 中的函数,将参数scipy.interpolate指定为。使用你的数组:kindzero

>>> from scipy.interpolate import interp1d
>>> f = interp1d(t,x,kind="zero")
>>> f(r)
array((10, 11, 12, 13))

请注意,“重新采样”数组中的最后一个元素是 13,而不是您在问题中要求的 14,而是f(5.001) = 14(*)。只要“重采样”数组与原始数组中的一个点匹配,插值函数就是不连续的。

(*)如果要bounds_error=False在.interp1dt

于 2013-01-30T23:11:50.917 回答
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]
于 2013-02-02T14:26:28.160 回答