簡體   English   中英

使用 Numpy 進行多維索引

[英]Multi dimensional Indexing with Numpy

我正在使用一個 3 維數組,其定義如下:

x = np.zeros((dim1, dim2, dim3), dtype=np.float32)

插入一些數據后,僅當特定列中的值仍然為零時,我才需要應用函數。 我感興趣的列由包含正確索引的數組選擇

scale_idx = np.array([0,1,3])

因此我要做的是使用索引來選擇那些行和列。

起初我嘗試這樣做,對前二維使用布爾掩碼,對第三維使用數組:

x[x[:,:,scale_idx].any(axis =2)] ,scale_idx]

但我收到此錯誤:

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (2,) (3,) 

如果我將最后一個索引更改為:我得到了我感興趣的所有行,但我得到了所有可能的列,我期望最后一個數組將充當索引器,如https://docs.scipy 中所述.org/doc/numpy/user/basics.indexing.html

x[x[:,:,scale_idx].any(axis =2)]

我的scale_idx應該被解釋為列索引器,但實際上被解釋為行索引,因此,由於只有 2 行符合條件但我有 3 個索引,我得到一個IndexError

我找到了一種解決方法,使用

x[x[:,:,scale_idx].any(axis =2)][:,:,scale_idx]

但它有點難看,因為它是一個切片,我無法修改原始數組。

有人願意向我解釋我做錯了什么嗎?

編輯:感謝@hpaulj,我設法隔離了我需要的單元格,之后我創建了一個與所選值形狀相同的矩陣,並將這些值分配給蒙面單元格,令我驚訝的是,新值不是我剛剛設置的那些,而是一些我無法弄清楚它們來自哪里的隨機整數。 重現代碼:

scale_idx = np.array([0,3,1])
b = x[:,:,scale_idx].any(axis =2)
I, J = np.nonzero(b)
x[I[:,None], J[:,None], scale_idx] #this selects the correct cells
>>>
array([[ 50,  50,  50],
     [100, 100, 100],
     [100, 100, 100]])
scaler.transform(x[I[:,None], J[:,None], scale_idx]) #sklearn standard scaler, returns a matrix with the scaled values
>>>
array([[-0.50600345, -0.5445559 , -1.2957878 ],
     [-0.50600345, -0.25915199, -1.22266904],
     [-0.50600345, -0.25915199, -1.22266904]]) 
x[I[:,None], J[:,None], scale_idx] = scaler.transform(x[I[:,None], J[:,None], scale_idx]) #assign the new values to the selected cells
x[I[:,None], J[:,None], scale_idx] #check the new values

array([[0, 2, 0],
     [0, 6, 2],
     [0, 6, 2]])

為什么新值與我期望的不同?

讓我們從indexing文檔中獲取 3d 布爾掩碼示例:

In [135]: x = np.arange(30).reshape(2,3,5) 
     ...: b = np.array([[True, True, False], [False, True, True]])                             
In [136]: x                                                                                    
Out[136]: 
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14]],

       [[15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29]]])
In [137]: b                                                                                    
Out[137]: 
array([[ True,  True, False],
       [False,  True,  True]])
In [138]: x[b]                                                                                 
Out[138]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29]])

這是一個二維數組。 掩碼b從前 2 個維度中選擇元素。 False值導致它跳過 [10...] 和 [15...] 行。

我們可以在最后一個維度上切片:

In [139]: x[b,:3]                                                                              
Out[139]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [20, 21, 22],
       [25, 26, 27]])

但是列表索引會產生錯誤(除非它的長度為 4):

In [140]: x[b,[0,1,2]]                                                                         
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-140-7f1dbec100f2> in <module>
----> 1 x[b,[0,1,2]]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (4,) (3,) 

原因是布爾掩碼有效地轉換為np.where數組的索引:

In [141]: np.nonzero(b)                                                                        
Out[141]: (array([0, 0, 1, 1]), array([0, 1, 1, 2]))

nonzero找到 4 個非零元素。 x[b]索引是:

In [143]: x[[0,0,1,1],[0,1,1,2],:]                                                             
Out[143]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24],
       [25, 26, 27, 28, 29]])

https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#boolean-array-indexing

然后形狀不匹配變得更加明顯:

In [144]: x[[0,0,1,1],[0,1,1,2],[1,2,3]]                                                       
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-144-1efd76049cb0> in <module>
----> 1 x[[0,0,1,1],[0,1,1,2],[1,2,3]]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (4,) (3,) 

如果列表大小匹配,則索引會運行,但會生成“對角線”,而不是塊:

In [145]: x[[0,0,1,1],[0,1,1,2],[1,2,3,4]]                                                     
Out[145]: array([ 1,  7, 23, 29])

正如您發現兩階段索引工作 - 但不適用於設置值

In [146]: x[[0,0,1,1],[0,1,1,2]][:,[1,2,3]]                                                    
Out[146]: 
array([[ 1,  2,  3],
       [ 6,  7,  8],
       [21, 22, 23],
       [26, 27, 28]])

我們可以通過“轉置”最后一個索引列表來獲取塊:

In [147]: x[[0,0,1,1],[0,1,1,2],[[1],[2],[3]]]                                                 
Out[147]: 
array([[ 1,  6, 21, 26],
       [ 2,  7, 22, 27],
       [ 3,  8, 23, 28]])

好的,這是轉置。 我們可以對其應用轉置。 或者我們可以先轉置b數組:

In [148]: I,J=np.nonzero(b)                                                                    
In [149]: x[I[:,None], J[:,None], [1,2,3]]                                                     
Out[149]: 
array([[ 1,  2,  3],
       [ 6,  7,  8],
       [21, 22, 23],
       [26, 27, 28]])

這適用於設置

In [150]: x[I[:,None], J[:,None], [1,2,3]]=0                                                   
In [151]: x                                                                                    
Out[151]: 
array([[[ 0,  0,  0,  0,  4],
        [ 5,  0,  0,  0,  9],
        [10, 11, 12, 13, 14]],

       [[15, 16, 17, 18, 19],
        [20,  0,  0,  0, 24],
        [25,  0,  0,  0, 29]]])

這是一個很長的答案。 我對正在發生的事情有一個大致的了解,但需要弄清楚細節。 另外,您需要了解正在發生的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM