的lenght這裏有一個量化的方式利用的masking
和maximum-accumulation
與np.maximum.accumulate
-
i[np.maximum.accumulate(np.where(a==0, np.arange(len(a)), 0))]
另一種方式把它是 -
i[np.maximum.accumulate(np.arange(len(a)) * (a==0))]
說明
剛進入這裏的故事肉的細節,讓我們分解步驟 -
1]輸入:
In [83]: a = np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
...: i = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
...:
2]因此,輸入a
是:
In [84]: a
Out[84]: array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
3]獲取覆蓋長度的範圍數組a
:
In [85]: np.arange(len(a))
Out[85]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
4]現在m問出在地方,其中a是1的範圍內排列,留給我們相對應的元件a是0:
In [86]: np.arange(len(a)) * (a==0)
Out[86]: array([0, 0, 0, 0, 4, 5, 6, 0, 0, 9, 0])
5]使用最大累加來創建斜坡結構根據需要:
In [87]: np.maximum.accumulate(np.arange(len(a)) * (a==0))
Out[87]: array([0, 0, 0, 0, 4, 5, 6, 6, 6, 9, 9])
6最後索引爲i個與這些號碼爲期望的輸出:
In [88]: i[np.maximum.accumulate(np.arange(len(a)) * (a==0))]
Out[88]: array([0, 0, 0, 0, 4, 5, 6, 6, 6, 9, 9])
運行測試
個
途徑 -
def FranciscoRodriguez(a,i): # @Francisco Rodríguez's soln
x = []
for idx,val in enumerate(a):
if val==0: x.append(i[idx])
elif val==1: x.append(x[-1])
return x
def ThomasGuenet(a,i): # @ThomasGuenet 's soln
x = np.zeros(len(a))
for j, aa in enumerate(a):
if j == 0:
x[j] == aa
elif aa == 1:
x[j] = x[j-1]
else:
x[j] = i[j]
return x
def vectorizedApp1(a,i):
return i[np.maximum.accumulate(np.where(a==0, np.arange(len(a)), 0))]
def vectorizedApp2(a,i):
return i[np.maximum.accumulate(np.arange(len(a)) * (a==0))]
計時 -
讓我們的瓷磚給定的樣本,以創造更大的數據集,並測試了所有的解決方案:
In [78]: a = np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
...: i = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
...:
...: a = np.tile(a,100000)
...: i = np.tile(i,100000)
...:
In [79]: %timeit FranciscoRodriguez(a,i)
...: %timeit ThomasGuenet(a,i)
...: %timeit vectorizedApp1(a,i)
...: %timeit vectorizedApp2(a,i)
...:
1 loop, best of 3: 328 ms per loop
1 loop, best of 3: 331 ms per loop
100 loops, best of 3: 6.07 ms per loop
100 loops, best of 3: 6.77 ms per loop
'ufunc.accumulate'非常方便,以前我從來沒有用過! – FooBar
你釘了它的人!我很驚訝! – FcoRodr