<p>不知怎的,在我开始之前,这在我的脑海里看起来更容易。幸运的是,与此同时,其他人已经提出了解决方案。因此,是时候将我的解决方案与其他解决方案进行比较了:</p>
<pre><code>import numpy as np
from timeit import timeit
# original
def f1(signal):
signal_prev = signal[:-1]
signal_prev = np.pad(signal_prev,(1,0), mode='constant', constant_values=(0))
arr = np.array([signal,signal_prev], dtype=int)
arr = np.transpose(arr)
signal_sum = np.array([], dtype=int)
for x in arr:
if np.sign(x[0]*x[1]) > 0:
signal_sum = np.append(signal_sum, signal_sum[-1] + x[1])
else:
signal_sum= np.append(signal_sum, x[0])
arr_sum = np.array([signal, signal_sum])
return np.transpose(arr_sum)
#Pierre D
def f2(s):
# make a copy and ensure np.array (in case list was given)
s = np.array(s).copy()
idx = np.nonzero(np.diff(s))[0] # last of each group
off = np.diff(np.concatenate(([0], np.cumsum(s)[idx])))
s[idx + 1] -= off
return np.cumsum(s)
#sai
def f3(signal):
normal_cumsum = np.cumsum(signal)
reset_sums = np.roll(np.where(np.diff(np.sign(signal), append=np.sign(signal[-1])) != 0, normal_cumsum, np.zeros_like(signal)), 1)
ffill_idxs = np.hstack((np.squeeze(np.argwhere(reset_sums != 0)), np.array([len(signal)])))
for start, end in zip(ffill_idxs[:-1], ffill_idxs[1:]):
reset_sums[start:end] = reset_sums[start]
return normal_cumsum - reset_sums
#Tis Chris sawtooth 0
def f4(arr):
cumsum_ix = np.zeros_like(arr)
cumsum_ix[ 1: ] = (( arr[ :-1 ] - arr[ 1: ] ) != 0 ).cumsum()
# cumsum_ix incrememnts for each sign change.
result = np.zeros_like( arr )
for i in range( 0, cumsum_ix[ -1 ] + 1 ):
# For each cumsum_ix select those items and generate the cumsums.
result[ cumsum_ix==i ] = arr[ cumsum_ix==i ].cumsum()
return result
#c'est moi
def f5(signal):
ind = np.where(np.diff(signal, prepend=0).astype(bool))
signalcount = signal.copy()
signalcount[ind] = signalcount[ind] + np.diff(ind, prepend=0) * np.sign(signal[ind])
return signalcount.cumsum()
</code></pre>
<p>首先,让我们检查它们是否都返回相同的结果。事实证明,sai的解决方案有时会生成错误的数组:</p>
<pre><code>nxd = 20 #array length
s = np.random.choice([1, -1], size=nxd)
#Integrity check
print(f1(s).T[1])
#[-1 -2 1 -1 1 2 -1 -2 -3 1 2 3 -1 -2 1 -1 1 -1 1 -1]
print(f2(s))
#[-1 -2 1 -1 1 2 -1 -2 -3 1 2 3 -1 -2 1 -1 1 -1 1 -1]
print(f3(s))
#sometimes the counting is incorrect
#[-1 -2 1 -1 1 2 1 ->0<- -1 1 2 3 2 1 1 -1 1 -1 1 -1]
print(f4(s))
#[-1 -2 1 -1 1 2 -1 -2 -3 1 2 3 -1 -2 1 -1 1 -1 1 -1]
print(f5(s))
#[-1 -2 1 -1 1 2 -1 -2 -3 1 2 3 -1 -2 1 -1 1 -1 1 -1]
</code></pre>
<p>现在,较短阵列的计时:</p>
<pre><code>ntime = 50 #number of test runs
nxd = 2000 #array length
s = np.random.choice([1, -1], size=nxd)
print(timeit(lambda: f1(s), number=ntime))
#1.1028546000000001
print(timeit(lambda: f2(s), number=ntime))
#0.004060500000000022 <--- best timing
print(timeit(lambda: f3(s), number=ntime))
#0.0505989
print(timeit(lambda: f4(s), number=ntime))
#0.4808455999999999
print(timeit(lambda: f5(s), number=ntime))
#0.0046319999999999695
</code></pre>
<p>和更长的阵列:</p>
<pre><code>ntime = 5 #number of test runs
nxd = int(1e6) #array length
s = np.random.choice([1, -1], size=nxd)
#print(timeit(lambda: f1(s), number=ntime))
#It took too long to wait for this result
print(timeit(lambda: f2(s), number=ntime))
#0.22104029999999986 <--- again the best timing
print(timeit(lambda: f3(s), number=ntime))
#2.402051
#print(timeit(lambda: f4(s), number=ntime))
#took too long
print(timeit(lambda: f5(s), number=ntime))
#0.2280369000000002
</code></pre>
<p>因此,Pierre D的建议是您的最佳选择(到目前为止)</p>