蟒蛇。检测矢量方向的变化

时间:2017-12-06 03:31:30

标签: python numpy

我有一个向量y2,可以递增或递减1.我想要的是创建另一个向量y1,显示numpy何时改变方向。

我无法在import matplotlib.pyplot as plt import numpy as np 中找出如何执行此操作。

由于y

中缺少逗号,编辑了更新的情节

enter image description here

import matplotlib.pyplot as plt
import numpy as np

y = np.array([0,0,1,1,2,2,1,0,-1,-1,0,0,1])

x = np.arange(len(y))

y2 = np.array([0,0,1,0,0,0,-1,0,0,0,1,0,0])

plt.plot(x, y, label='y - Actual')
plt.plot(x, y2, label='y2 - Desired')
plt.legend()
plt.show()

编辑:已修复y中缺少的逗号

{{1}}

3 个答案:

答案 0 :(得分:2)

编辑:现在还处理超出规格的输入(增量在-1,0,1之外)。

这里的速度稍快(暂时)(pp是我,D是@Divakar):

# n = 10
# pp                    0.02363790 ms
# D                     0.03705720 ms
# n = 1000
# pp                    0.03609150 ms
# D                     0.05877410 ms
# n = 1000000
# pp                   22.63471480 ms
# D                    36.92147740 ms

包括基准测试的代码:

import numpy as np

import types
from timeit import timeit

def setup_data(n, allow_out_of_spec=True):
    if allow_out_of_spec:
        data = {'y': np.cumsum(np.random.randint(0, 10, (n,))
                               * np.random.randint(-1, 2, (n,)))}
    else:
        data = {'y': np.cumsum(np.random.randint(-1, 2, (n,)))}
    return data

# mine
def f_pp(y, allow_out_of_spec=True):
    if allow_out_of_spec:
        d = np.sign(np.diff(y))
    else:
        d = np.diff(y)
    ud = np.flatnonzero(d)
    uds = d[ud]
    chng = ud[np.r_[True, uds[1:] != uds[:-1]]]

    out = np.zeros(len(y), dtype=int)
    out[1:][chng] = d[chng]
    return out

# @Divakar's
def f_D(y):
    s0 = np.flatnonzero(y[1:] > y[:-1])+1
    s1 = np.flatnonzero(y[1:] < y[:-1])+1

    idx0 = np.searchsorted(s1,s0,'right')
    s0c = s0[np.r_[True,idx0[1:] > idx0[:-1]]]

    idx1 = np.searchsorted(s0c,s1,'right')
    s1c = s1[np.r_[True,idx1[1:] > idx1[:-1]]]

    out = np.zeros(len(y),dtype=int)
    out[s0c] = 1
    out[s1c] = -1
    return out

for n in (10, 1000, 1000000):
    data = setup_data(n)
    ref = np.array(f_pp(**data))
    print(f'n = {n}')
    for name, func in list(globals().items()):
        if not name.startswith('f_') or not isinstance(func, types.FunctionType):
            continue
        try:
            assert np.allclose(ref, func(**data))
            print("{:16s}{:16.8f} ms".format(name[2:], timeit(
                'f(**data)', globals={'f':func, 'data':data}, number=10)*100))
        except:
            print("{:16s} apparently failed".format(name[2:]))

答案 1 :(得分:1)

这是一种方式 -

def detect_ups_downs(y):
    s0 = np.flatnonzero(y[1:] > y[:-1])+1
    s1 = np.flatnonzero(y[1:] < y[:-1])+1

    idx0 = np.searchsorted(s1,s0,'right')
    s0c = s0[np.r_[True,idx0[1:] > idx0[:-1]]]

    idx1 = np.searchsorted(s0c,s1,'right')
    s1c = s1[np.r_[True,idx1[1:] > idx1[:-1]]]

    out = np.zeros(len(y),dtype=int)
    out[s0c] = 1
    out[s1c] = -1
    return out

示例运行 -

In [92]: y = np.array([0,0,1,2,3,4,1,0,-1-1,0,0,1,0,8,8,9,-4,-6,4,-2,2])

In [93]: np.c_[y, detect_ups_downs(y)]
Out[93]: 
array([[ 0,  0],
       [ 0,  0],
       [ 1,  1],
       [ 2,  0],
       [ 3,  0],
       [ 4,  0],
       [ 1, -1],
       [ 0,  0],
       [-2,  0],
       [ 0,  1],
       [ 0,  0],
       [ 1,  0],
       [ 0, -1],
       [ 8,  1],
       [ 8,  0],
       [ 9,  0],
       [-4, -1],
       [-6,  0],
       [ 4,  1],
       [-2, -1],
       [ 2,  1]])

答案 2 :(得分:-1)

尝试采用衍生物:

dy = y[1:] - y[:-1]

然后检查相邻点是否已切换衍生符号:

increasing = dy > 0
decreasing = dy < 0
saddle = dy == 0

change_increasing = increasing[1:] and decreasing[:-1]
change_decreasing = decreasing[1:] and increasing[:-1]

将所有信息汇集在一起​​:

changes = np.zeros_like(dy)

changes[0] = (1 * increasing[0]) + (-1 * decreasing[0])
changes[1:][change_increasing] = 1
changes[1:][change_decreasing] = -1
changes[saddle] = 0

print(changes)