NumPy nxn配列をスライスしたい。任意その配列の m 行と列を選択して (つまり、行/列の数にパターンがない)、新しい mxm 配列を作成します。この例では、配列が 4x4 で、そこから 2x2 配列を抽出したいとします。
配列は次のとおりです。
from numpy import *
x = range(16)
x = reshape(x,(4,4))
print x
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
削除する行と列は同じです。最も簡単なケースは、先頭または末尾にある 2x2 サブマトリックスを抽出したい場合です。
In [33]: x[0:2,0:2]
Out[33]:
array([[0, 1],
[4, 5]])
In [34]: x[2:,2:]
Out[34]:
array([[10, 11],
[14, 15]])
しかし、別の行/列の組み合わせを削除する必要がある場合はどうでしょうか? 1 行目と 3 行目を削除してサブマトリックスを抽出する必要がある場合はどうでしょうか[[5,7],[13,15]]
? 行/行の構成は任意です。どこかで、行と列の両方のインデックスの配列/リストを使用して配列にインデックスを付ける必要があると読みましたが、うまくいかないようです。
In [35]: x[[1,3],[1,3]]
Out[35]: array([ 5, 15])
私が見つけた一つの方法は次のとおりです。
In [61]: x[[1,3]][:,[1,3]]
Out[61]:
array([[ 5, 7],
[13, 15]])
これに関する最初の問題は、ほとんど読めないことですが、それでも我慢できます。もっと良い解決策をお持ちの方がいらっしゃれば、ぜひお聞かせください。
他には、私が読んだフォーラムで配列を配列でインデックスすると、NumPy は目的の配列のコピーを作成するよう強制されるため、大きな配列を扱うときに問題が発生する可能性があります。なぜそうなるのでしょうか。また、このメカニズムはどのように機能するのでしょうか。
ベストアンサー1
この質問に答えるには、Numpy で多次元配列のインデックス付けがどのように機能するかを確認する必要があります。まず、x
質問の配列があるとします。 に割り当てられたバッファには、x
0 から 15 までの 16 個の昇順の整数が含まれます。 1 つの要素 (たとえば ) にアクセスする場合x[i,j]
、NumPy はバッファの先頭を基準としたこの要素のメモリ位置を把握する必要があります。これは、実際には を計算することによって行われますi*x.shape[1]+j
(実際のメモリ オフセットを取得するには、int のサイズを乗算します)。
のような基本的なスライスによってサブ配列を抽出するとy = x[0:2,0:2]
、結果のオブジェクトは基になるバッファを と共有しますx
。しかし、 にアクセスするとどうなるでしょうか。 に属するデータはメモリ内で連続していないため、NumPy は を使用して配列へのオフセットを計算することy[i,j]
ができません。i*y.shape[1]+j
y
NumPyは、この問題を次のように解決します。進歩にアクセスするためのメモリ オフセットを計算する場合x[i,j]
、実際に計算されるのは次のようになりますi*x.strides[0]+j*x.strides[1]
(これには、int のサイズの係数がすでに含まれています)。
x.strides
(16, 4)
上記のように抽出されるとy
、NumPyは新しいバッファを作成しませんが、する同じバッファを参照する新しい配列オブジェクトを作成します (そうでない場合y
は と等しくなりますx
)。新しい配列オブジェクトは異なる形状になり、バッファへの開始オフセットも異なる可能性がありますが、ストライドは(少なくともこの場合は)x
と共通になります。x
y.shape
(2,2)
y.strides
(16, 4)
この方法では、メモリ オフセットを計算するとy[i,j]
正しい結果が得られます。
しかし、NumPyは のような場合どうすればよいのでしょうかz=x[[1,3]]
? 元のバッファが に使用されている場合、ストライドメカニズムでは正しいインデックス付けができませんz
。NumPyは理論的にはできたストライドよりも洗練されたメカニズムを追加しますが、これにより要素へのアクセスが比較的高価になり、配列の全体的な概念に反することになります。さらに、ビューはもはや本当に軽量なオブジェクトではなくなります。
これについては、インデックスに関するNumPyドキュメント。
ああ、実際の質問を忘れるところでした。複数のリストでインデックスを期待どおりに機能させる方法は次のとおりです。
x[[[1],[3]],[1,3]]
これは、インデックス配列が放送された一般的な形状に。もちろん、この特定の例では、基本的なスライスでも十分です。
x[1::2, 1::2]