0

我想使用某種類型的索引數組(索引數組的樣式/格式打開以獲得建議)從基本數組中獲取子數組的numpy數組。我可以用for循環輕鬆做到這一點,但想知道是否有巧妙的方式來使用numpy廣播?如何矢量化使用索引數組獲取numpy數組的子數組

約束:子數組保證大小相同。

up_idx = np.array([[0, 0], 
        [0, 2], 
        [1, 1]]) 
lw_idx = np.array([[2, 2], 
        [2, 4], 
        [3, 3]]) 
base = np.array([[1, 2, 3, 4], 
       [5, 6, 7, 8], 
       [9, 10, 11, 12]]) 

samples = [] 

for index in range(up_idx.shape[0]): 
    up_row = up_idx[index, 0] 
    up_col = up_idx[index, 1] 
    lw_row = lw_idx[index, 0] 
    lw_col = lw_idx[index, 1] 

    samples.append(base[up_row:lw_row, up_col:lw_col]) 

samples = np.array(samples) 

print(samples) 
> [[[ 1 2] 
    [ 5 6]] 

    [[ 3 4] 
    [ 7 8]] 

    [[ 6 7] 
    [10 11]]] 

我已經試過:

vector_s = base[up_idx[:, 0]:lw_idx[:, 1], up_idx[:, 1]:lw_idx[:, 1]] 

但那只是無意義的似乎。

+0

'up_pt'是怎麼樣的?形狀? – kmario23

+0

哦對不起。我在發佈之前更改了變量,顯然錯過了。 – dranobob

回答

0

我不認爲有一種快速的方法可以通過numpy廣播操作來實現這一點 - 一方面,您設置問題的方式並不能保證生成的子陣列將具有相同的形狀,並且因此能夠適合單個輸出陣列。

解決這個問題的最簡潔有效的方法可能是通過列表理解;例如

result = np.array([base[i1:i2, j1:j2] for (i1, j1), (i2, j2) in zip(up_idx, lw_idx)]) 

除非您的基陣非常大,否則這應該不是什麼瓶頸。

如果您有不同的問題約束(即每種情況下的大小相同),則可以基於花式索引提出更快的矢量化解決方案。例如,如果每片爲大小兩個(如上面的例子),那麼你可以使用花哨的索引像這樣以獲得相同的結果:

i, j = up_idx.T[:, :, None] + np.arange(2) 
result = base[i[:, :, None], j[:, None]] 

理解這個花哨的索引的關鍵是要認識到,結果跟隨索引數組的廣播形狀。

+0

謝謝你的回覆。我應該提到這些子陣列將保證相同的大小。讓他們在一個單一的數組中是我已經向量化的下一部分代碼的一個要求。 – dranobob

+0

我已經更新了問題約束:) – dranobob

+0

無關於切片做什麼? – dranobob