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のブロードキャスト操作でこれを行うための速い方法はないと思います.1つは、問題を設定する方法によって、結果のサブアレイが同じ形状になるという保証はありませんしたがって、単一の出力配列に適合することができる。

これを解決する最も簡潔で効率的な方法はおそらくリストの理解によるものです。例えば

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

ベース配列が非常に大きい場合を除き、これはボトルネックではありません。

異なる制約(すべてのケースで同じサイズのスライス)がある場合は、ファンシーインデックスに基づいて高速化されたベクトル化ソリューションを考え出すことができます。たとえば、すべてのスライスのサイズが2である場合(上記のあなたの例のように)、あなたは同じ結果を得るために、このような派手なインデックスを使用することができます。

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

この空想のインデックスを理解する鍵は、ことを実現することです結果は、インデックス配列のブロードキャストされた形に従います。

+0

お返事ありがとうございます。私はサブアレイが同じサイズを保証されることに言及すべきである。それらを単一の配列にまとめることは、私が既にベクトル化している次のコードセクションの必要条件です。 – dranobob

+0

私は問題の制約を更新しました:) – dranobob

+0

スライシングに関してNoneは何をしますか? – dranobob

関連する問題