[英]NumPy indexing: broadcasting with Boolean arrays
與此問題相關,我通過布爾數組遇到了索引行為,並且無法理解廣播。 我們知道可以使用整數索引和廣播在2維中為NumPy數組建立索引。 這是在docs中指定的:
a = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b1 = np.array([False, True, True])
b2 = np.array([True, False, True, False])
c1 = np.where(b1)[0] # i.e. [1, 2]
c2 = np.where(b2)[0] # i.e. [0, 2]
a[c1[:, np.newaxis], c2] # or a[c1[:, None], c2]
array([[ 4, 6],
[ 8, 10]])
但是,這對於布爾數組不起作用。
a[b1[:, None], b2]
IndexError: too many indices for array
備用numpy.ix_
適用於整數和布爾數組。 這似乎是因為ix_
對布爾數組執行特定的操作以確保一致的處理。
assert np.array_equal(a[np.ix_(b1, b2)], a[np.ix_(c1, c2)])
array([[ 4, 6],
[ 8, 10]])
所以我的問題是:為什么廣播只能使用整數,而不能使用布爾數組? 是否記錄了這種行為? 還是我誤解了一個更根本的問題?
正如@Divakar 在評論中指出的那樣 ,布爾高級索引的行為就像它們首先通過np.nonzero
饋入然后一起廣播一樣, 請參閱相關文檔以獲取詳細說明 。 要引用文檔,
通常,如果索引包含布爾數組,則結果將與將
obj.nonzero()
插入相同位置並使用上述整數數組索引機制相同。x[ind_1, boolean_array, ind_2]
等效於x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]
。
[...]
可以通過obj.nonzero()
類比來最好地理解將多個布爾索引數組或布爾與整數索引數組組合在一起的obj.nonzero()
。ix_
函數還支持布爾數組,並且可以正常工作。
在您的情況下,廣播不一定會成為問題,因為兩個數組都只有兩個非零元素。 問題是結果中的維數:
>>> len(b1[:,None].nonzero())
2
>>> len(b2.nonzero())
1
因此索引表達a[b1[:,None], b2]
將相當於a[b1[:,None].nonzero() + b2.nonzero()]
,這將使一個長度為3的元組內a
,對應於3d數組索引。 因此,您會看到有關“索引過多”的錯誤。
文檔中提到的驚喜與您的示例非常接近:如果您未注入該單例維度該怎么辦? 從length-3和length-4布爾數組開始,您將得到一個length-2高級索引,即大小為(2,)
的1d數組。 這永遠不是您想要的,這使我們在該主題中又經歷了一些瑣事。
在計划改進高級索引方面進行了很多討論,請參閱正在進行的草案NEP 21 。 問題的要點是,盡管已明確記錄,但numpy中的花式索引具有一些非常古怪的功能,這些功能實際上對任何事情都沒有用,但是如果您通過產生令人驚訝的結果而不是錯誤而犯了錯誤,它們可能會咬人。
NEP的相關報價:
涉及多個數組索引的混合案例也令人驚訝,並且問題也較少,因為當前行為是如此無用,以致於在實踐中很少遇到。 當布爾數組索引與另一個布爾數組或整數數組混合時,布爾數組將轉換為整數數組索引(等效於
np.nonzero()
),然后進行廣播。 例如,索引尺寸的2D陣列(2, 2)
像x[[True, False], [True, False]]
產生具有形狀的1D向量(1,)
不是2D子矩陣與形狀(1, 1)
。
現在,我強調NEP尚在開發中,但是NEP當前狀態的建議之一是在諸如此類的高級索引情況下禁止布爾數組,而僅允許它們在“外部索引”中使用。 ”場景,即np.ix_
可以幫助您如何使用布爾數組:
布爾索引在概念上是外部索引。 以傳統索引(即當前行為)的方式與其他高級索引一起廣播通常沒有幫助或沒有明確定義。 因此,希望“非零”加廣播行為的用戶可以手動執行此操作。
我的觀點是,布爾高級索引的行為及其不贊成使用的狀態(或缺少它們)在不久的將來可能會發生變化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.