說,一個有以下numpy的數組:如何一次從numpy數組中排除幾個範圍?
X = numpy.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
現在,一個如何從X
範圍X[0:2]
,X[6:8]
和X[12:14]
一次,所以人會在結果X= [2, 2, 2, 4, 4, 4]
獲取數組排除?
說,一個有以下numpy的數組:如何一次從numpy數組中排除幾個範圍?
X = numpy.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
現在,一個如何從X
範圍X[0:2]
,X[6:8]
和X[12:14]
一次,所以人會在結果X= [2, 2, 2, 4, 4, 4]
獲取數組排除?
你可以使用np.r_
到的範圍,組合成一維數組:
In [18]: np.r_[0:2,6:8,12:14]
Out[18]: array([ 0, 1, 6, 7, 12, 13])
然後使用np.in1d
創建在這些索引位置爲True的布爾數組:
In [19]: np.in1d(np.arange(len(X)), (np.r_[0:2,6:8,12:14]))
Out[19]:
array([ True, True, False, False, False, False, True, True, False,
False, False, False, True, True, False], dtype=bool)
然後用~
to invert布爾數組:
In [11]: X = np.array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5])
In [12]: X[~np.in1d(np.arange(len(X)), (np.r_[0:2,6:8,12:14]))]
Out[12]: array([1, 2, 2, 2, 3, 4, 4, 4, 5])
注意X[12:14]
捕獲只有前兩個5的。剩下一個5,所以結果是array([1, 2, 2, 2, 3, 4, 4, 4, 5])
,而不是array([1, 2, 2, 2, 3, 4, 4, 4])
。
Python中的切片範圍是半開間隔。包含左側索引,但正確的索引不包含。所以X[12:14]
選擇X[12]
和X[13]
,但不是X[14]
。有關Guido van Rossum對Python爲何使用半開區間的解釋,請參閱this post。
要得到的結果[2, 2, 2, 4, 4, 4]
你需要添加一個到右側(結尾)指數爲每個切片:
In [17]: X[~np.in1d(np.arange(len(X)), (np.r_[0:3,6:9,12:15]))]
Out[17]: array([2, 2, 2, 4, 4, 4])
您可以使用這樣的事情:
numbers = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]
exclude = set(range(0,2) + range(6,8) + range(12,14))
[n for n in numbers if n not in exclude]
或:
[i for i in nums if i not in xrange(0,2) and i not in xrange(6,8) and i not in xrange(12,14)]
結果:
[2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5]
您可以撥打np.delete
3次,自@nneonneo在評論中表示,它不需要計算範圍偏移就可以反轉。 :
>>> np.delete(np.delete(np.delete(X,np.s_[12:14]),np.s_[6:8]),np.s_[0:2])
array([1, 2, 2, 2, 3, 4, 4, 4, 5])
在以@unutbu
的答案,我建議np.delete
評論。這裏有幾個計時
更大的測試序列:
In [445]: A=np.arange(1000)
@ unutbu的回答是:
In [446]: timeit A[~np.in1d(np.arange(len(A)), (np.r_[10:50:3,100:200,300:350]))].shape
1000 loops, best of 3: 454 µs per loop
相同的索引列表,但使用np.delete
- 大約3倍提速
In [447]: timeit np.delete(A,np.r_[10:50:3,100:200,300:350]).shape
10000 loops, best of 3: 166 µs per loop
但做一個簡單的布爾掩模更快。早些時候,我推斷,np.delete
基本上做到這一點,但它必須有一些額外的開銷(包括用於處理多個維度的能力):
In [448]: %%timeit
ind=np.ones_like(A,bool)
ind[np.r_[10:50:3,100:200,300:350]]=False
A[ind].shape
.....:
10000 loops, best of 3: 71.5 µs per loop
np.delete
具有當輸入爲片,這可能比快了不同的策略布爾索引。但它一次只處理一個切片,因此@ Kasramvd顯示的嵌套刪除。我打算增加這個時間。
連接多個切片是另一種選擇。
np.r_
也涉及到一個循環,但它只是在切片上。基本上它迭代切片,擴展每個作爲範圍,並連接它們。在我的最快的情況下,它的運行時間的2/3負責:
In [451]: timeit np.r_[10:50:3,100:200,300:350]
10000 loops, best of 3: 41 µs per loop
In [453]: %%timeit x=np.r_[10:50:3,100:200,300:350]
ind=np.ones_like(A,bool)
ind[x]=False
A[ind].shape
.....:
10000 loops, best of 3: 24.2 µs per loop
嵌套刪除有相當不錯的表現:
In [457]: timeit np.delete(np.delete(np.delete(A,slice(300,350)),
slice(100,200)),slice(10,50,3)).shape
10000 loops, best of 3: 108 µs per loop
np.delete
,當給定切片刪除,將slice複製到結果數組(delete塊之前和之後的塊)。我可以通過連接幾個切片來近似。我在這裏使用第一塊的刪除操作,而不是花時間寫一個純副本。它仍然比最好的布爾掩碼錶達式更快。
In [460]: timeit np.concatenate([np.delete(A[:100],slice(10,50,3)),
A[200:300],A[350:]]).shape
10000 loops, best of 3: 65.7 µs per loop
我可以用這個切片取下delete
,雖然10:50範圍內的順序弄亂了。我懷疑這是,理論上,最快:
In [480]: timeit np.concatenate([A[:10], A[11:50:3], A[12:50:3],
A[50:100], A[200:300], A[350:]]).shape
100000 loops, best of 3: 16.1 µs per loop
一個重要的注意 - 這些方案正在與非重疊片測試。有些可能與重疊一起工作,有些可能不會。
這些範圍如何/在哪裏存儲? – Divakar
我認爲你的意思是'X [0:3],X [6:9] .x [12:15]'? –
您需要循環切片的其中一種方法。一種解決方案可以讓'np.r_'做到這一點,另一種解決方案重複使用'delete',另一種解決方案組合切片。 – hpaulj