我希望我可以使用np.where或一些等效(和高效)的numpy函数构造以下算法:
def generate_signal(r):
signal = np.zeros(len(r), dtype=int)
lastSignal = 0
for i in range(len(r)):
if r[i] <= 30:
lastSignal = 1
elif r[i] >= 60:
lastSignal = 0
signal[i] = lastSignal
return signal
以下是输入/输出的一个示例:
r = np.array([50, 52, 59, 69, 47, 33, 27, 26, 20, 30, 33, 35, 58, 55, 48, 60, 68, 55, 43, 49, 33, 30, 22, 28])
s = generate_signal(r)
print(s) # This is the result: [0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1]
print(list(zip(r, s))) # A zipped result (in case it helps): [(50, 0), (52, 0), (59, 0), (69, 0), (47, 0), (33, 0), (27, 1), (26, 1), (20, 1), (30, 1), (33, 1), (35, 1), (58, 1), (55, 1), (48, 1), (60, 0), (68, 0), (55, 0), (43, 0), (49, 0), (33, 0), (30, 1), (22, 1), (28, 1)]
答案 0 :(得分:1)
构建结果信号的正负瞬态:
>>> pos_tran = np.maximum(0, np.diff(np.int8(r <= 30)))
>>> neg_tran = np.maximum(0, np.diff(np.int8(r >= 60)))
在第一次阳性瞬变之前消除负瞬态:
>>> neg_tran[0:np.nonzero(pos_tran)[0][0]] = 0
整合信号(累积和)并重新插入np.diff中丢失的前导0:
>>> np.insert(np.cumsum(pos_tran - neg_tran), 0, 0)
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1])
答案 1 :(得分:0)
您可以按如下方式使用np.repeat
:
import numpy as np
def f_pp():
rr = np.concatenate([[70], r, [70]])
l30, g60 = rr <= 30, rr >= 60
df, = np.where(l30 | g60)
reps = np.diff(df)
reps[0] -= 1
return l30[df[:-1]].astype(int).repeat(reps)
使用OP的示例和一些较大的(1000
元素)随机的计时和验证:
def generate_signal():
signal = np.zeros(len(r), dtype=int)
lastSignal = 0
for i in range(len(r)):
if r[i] <= 30:
lastSignal = 1
elif r[i] >= 60:
lastSignal = 0
signal[i] = lastSignal
return signal
def f_ff():
pos_tran = np.maximum(0, np.diff(np.int8(r <= 30)))
neg_tran = np.maximum(0, np.diff(np.int8(r >= 60)))
neg_tran[0:np.nonzero(pos_tran)[0][0]] = 0
return np.insert(np.cumsum(pos_tran - neg_tran), 0, 0)
from timeit import timeit
glb = globals()
kwds = dict(globals=glb, number=1000)
r = np.array([50, 52, 59, 69, 47, 33, 27, 26, 20, 30, 33, 35, 58, 55, 48, 60, 68, 55, 43, 49, 33, 30, 22, 28])
print('OP: {:8.4f} ms'.format(timeit(generate_signal, **kwds)))
print('ff: {:8.4f} ms'.format(timeit(f_ff, **kwds)))
print('pp: {:8.4f} ms'.format(timeit(f_pp, **kwds)))
print('ff correct:', np.all(generate_signal() == f_ff()))
print('pp correct:', np.all(generate_signal() == f_pp()))
R = np.random.randint(20, 70, (10, 1000))
print('OP: {:8.4f} ms'.format(sum(timeit(generate_signal, **kwds) for glb['r'] in R) / 10))
print('ff: {:8.4f} ms'.format(sum(timeit(f_ff, **kwds) for glb['r'] in R) / 10))
print('pp: {:8.4f} ms'.format(sum(timeit(f_pp, **kwds) for glb['r'] in R) / 10))
print('ff correct:', all(np.all(generate_signal() == f_ff()) for glb['r'] in R))
print('pp correct:', all(np.all(generate_signal() == f_pp()) for glb['r'] in R))
示例输出:
OP: 0.0138 ms
ff: 0.0405 ms
pp: 0.0121 ms
ff correct: True
pp correct: True
OP: 0.5386 ms
ff: 0.0539 ms
pp: 0.0215 ms
ff correct: False
pp correct: True