Indexing on ndarrays

ページ名:Indexing on ndarrays

インデックスを作成ndarrays

ndarrays標準のPython x[obj]構文を使用してインデックスを作成できます。ここで、xは配列、objは選択範囲です。obj応じて、基本インデックス、高度なインデックス、フィールドアクセスなど、さまざまな種類のインデックスが利用可能です。

以下の例のほとんどは、配列内のデータを参照する際にインデックスを使用する方法を示しています。これらの例は、配列への値の代入にも同様に有効です。具体的な例と代入の仕組みについては、「インデックス付き配列への値の代入」を参照してください。

Pythonでは、はと同等である ことに注意してください。後者は前者の単なる構文糖衣です。x[(exp1, exp2, ..., expN)]x[exp1, exp2, ..., expN]

基本インデックス

単一要素インデックス

単一要素のインデックス付けは、他の標準的なPythonシーケンスとまったく同じように機能します。インデックスは0から始まり、配列の末尾からのインデックス付けには負のインデックスも使用できます。

x = np.arange(10)
x[2]
2
x[-2]
8

各次元のインデックスをそれぞれ別の角括弧で囲む必要はありません。

x.shape = (2, 5) # now x is 2-dimensional
x[1, 3]
8
x[1, -1]
9

多次元配列を次元数よりも少ないインデックスでインデックス指定すると、サブディビジョン配列になることに注意してください。例:

x[0]
array([0, 1, 2, 3, 4])

つまり、指定された各インデックスは、選択された残りの次元に対応する配列を選択します。上記の例では、0 を選択すると、長さ 5 の残りの次元は指定されず、その次元とサイズの配列が返されます。返される配列はビューであることに注意してください。つまり、元の配列のコピーではなく、元の配列と同じメモリ上の値を指します。この場合、最初の位置 (0) にある 1 次元配列が返されます。したがって、返された配列に対して単一のインデックスを使用すると、単一の要素が返されます。つまり、次のようになります。

x[0][2]
2

したがって、2 番目のケースは、最初のインデックスの後に新しい一時配列が作成され、その後インデックスが 2 になるため、より非効率的であることに注意してください。x[0, 2] == x[0][2]

注記

NumPyはCオーダーインデックスを使用します。つまり、FortranやIDLとは異なり、NumPyでは通常、最後のインデックスが最も変化の速いメモリ位置を表します。FortranやIDLでは、最初のインデックスがメモリ内で最も変化の速い位置を表します。この違いは、混乱を招く大きな要因となります。

スライスとストライド

基本スライスは、Python の基本スライス概念を N 次元に拡張したものです。基本スライスは、objsliceオブジェクト (括弧内の表記で構築start:stop:step)、整数、またはスライス オブジェクトと整数のタプルである場合に発生します。Ellipsis また、newaxisオブジェクトをこれらに混在させることもできます。

N個の整数でインデックス付けする最も単純なケースでは、対応する項目を表す配列スカラーが返されます。Python と同様に、すべてのインデックスはゼロベースです。i 番目のインデックスの場合有効範囲はどこは配列の形状のi番目の要素です 。負のインデックスは配列の末尾から数えているものとして解釈されます (つまり、 つまり)

基本的なスライス操作によって生成される配列はすべて、常に 元の配列のビューです。

注記

NumPy のスライスは、文字列、タプル、リストなどの Python の組み込みシーケンスの場合とは異なり、コピーではなくビューcopy()を作成します。大きな配列から小さな部分を抽出する場合、抽出後に不要になる部分については注意が必要です。抽出された小さな部分には、元の大きな配列への参照が含まれており、そのメモリは、そこから派生したすべての配列がガベージコレクションされるまで解放されないためです。このような場合は、明示的な `requests` を使用することをお勧めします。

シーケンススライスの標準ルールは、次元ごとの基本的なスライス(ステップインデックスの使用を含む)に適用されます。覚えておくと便利な概念には、次のようなものがあります。

  • 基本的なスライス構文は、i:j:ki開始インデックス、 jが停止インデックス、kがステップ (これは、インデックス値ii + k、 …、i + (m - 1) kを 持つm個の要素 (対応する次元)を選択します。また、qrは、 j - iをkで割った商と余りであり、j - i = qk + rとなるため、 i + (m - 1) k < jとなる。例えば、次のようになる。

    x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    x[1:7:2]
    array([1, 3, 5])
  • 負のij は、それぞれn + in + jと解釈されます。ここで n は対応する次元の要素数です。負のk は、より小さなインデックスに向かってステップを進めることを意味します。上記の例から:

    x[-2:10]
    array([8, 9])
    x[-3:3:-1]
    array([7, 6, 5, 4])
  • nをスライス対象の次元の要素数とします。i指定されていない場合、 k > 0の場合はデフォルトで 0 、 k < 0の場合はn - 1になります。j が指定されていない場合、k > 0の場合はデフォルトでn 、 k < 0の場合 は-n-1になります。kが指定されていない場合はデフォルトで 1 になります 。と同じであり、この軸に沿ってすべてのインデックスを選択することを意味します。上記の例から::::

    x[5:]
    array([5, 6, 7, 8, 9])
  • 選択タプル内のオブジェクトの数がN未満の場合 、:以降の次元では が想定されます。例:

    x = np.array([1],[2],[3, 4],[5],[61:2]
    array([4],
    [5],
    [6
    ])

    x.shape
    (2, 3, 1)
    x[])
  • 整数i は、返されるオブジェクトの次元が 1 減る点をi:i+1 除いて、 と同じ値を返します。具体的には、 p番目の要素が整数 (および他のすべてのエントリ) である選択タプルは、次元がN - 1:の対応するサブ配列を返します。N = 1の場合、返されるオブジェクトは配列スカラーです。これらのオブジェクトについては、 「スカラー」 で説明します。

  • 選択タプルに、スライスオブジェクトであるp:番目のエントリを除く すべてのエントリが含まれている場合、返される配列は、要素ii+k、…、i + (m - 1) k < jの整数インデックスによって返されるサブ配列をp番目の軸に沿って積み重ねることによって形成される次元Nを持ちます。i:j:k

  • :スライス タプルに複数の非 エントリがある場合の基本スライスは、単一の非:エントリを使用したスライスの繰り返し適用のように動作し、非:エントリが順次取得されます (他のすべての非:エントリは に置き換えられます:)。したがって、 基本スライスではのように動作します。x[ind1, ..., ind2,:]x[ind1][..., ind2, :]

    警告

    上記は高度なインデックス作成には当てはまりません

  • スライスを使用して配列に値を設定することはできますが、(リストとは異なり)配列を拡張することはできません。設定する値のサイズは、配列 と同じ形状である必要があります(ブロードキャスト可能) 。x[obj] = valuex[obj]

  • スライス タプルは常にobjとして構築し 、表記法で使用できますx[obj]。スライス オブジェクトは、表記法の代わりに構築に使用できます[start:stop:step] 。たとえば、は としても実装できます。これは、任意の次元の配列で動作する汎用コードを構築する際に役立ちます。 詳細については、「プログラム内での可変数のインデックスの扱い」を参照してください。x[1:10:5, ::-1]obj = (slice(1, 10, 5), slice(None, None, -1)); x[obj]

次元インデックスツール

配列の形状と式や代入を簡単に一致させるためのツールがいくつかあります。

Ellipsis:選択タプルがすべての次元をインデックスするために必要なオブジェクトの数まで展開されます。ほとんどの場合、これは展開された選択タプルの長さが であることを意味しますx.ndim。省略記号は 1 つだけ存在する場合があります。上記の例から:

..., 0]
array(1, 2, 3],
[4, 5, 6
x[)

これは次と同等です:

:, :, 0]
array(1, 2, 3],
[4, 5, 6
x[)

newaxis選択タプル内の各オブジェクトは、結果として得られる選択の次元を1単位の長さの次元だけ拡張する役割を果たします。追加される次元はnewaxis 、選択タプル内でのオブジェクトの位置です。newaxisは のエイリアスであり NoneNoneの代わりに を使用することで同じ結果が得られます。上記の例から:

x[:, np.newaxis, :, :].shape
(2, 1, 3, 1)
x[:, None, :, :].shape
(2, 1, 3, 1)

これは、明示的な配列形状変更操作が必要となるような方法で、2つの配列を結合するのに便利です。例えば、次のようになります。

np.newaxis, :]
array(0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8
x = np.arange(5)
x[:, np.newaxis] + x[)

高度なインデックス作成

高度なインデックス作成は、選択オブジェクトobjがタプルではないシーケンス オブジェクト、ndarray整数型またはブール型の配列、あるいは少なくとも 1 つのシーケンス オブジェクトまたは ndarray (整数型またはブール型) を含むタプルである場合にトリガーされます。高度なインデックス作成には、整数型とブール型の 2 種類があります。

高度なインデックス作成は常にデータのコピーを返します(ビューを返す基本的なスライスとは対照的です)。

警告

高度なインデックスの定義は、 とが根本的に異なることを意味します。後者は と同等であり、基本的な選択がトリガーされますが、前者は高度なインデックスがトリガーされます。この違いが生じる理由を必ず理解してください。x[(1, 2, 3),]x[(1, 2, 3)]x[1, 2, 3]

整数配列のインデックス指定

整数配列のインデックス付けにより、 N次元のインデックスに基づいて配列内の任意の項目を選択できます。各整数配列は、その次元における複数のインデックスを表します。

インデックス配列では負の値も使用可能で、単一のインデックスやスライスの場合と同様に機能します。

x = np.arange(10, 1, -1)
x
array([10, 9, 8, 7, 6, 5, 4, 3, 2])
x[np.array([3, 3, 1, 8])]
array([7, 7, 9, 2])
x[np.array([3, 3, -3, 8])]
array([7, 7, 4, 2])

インデックス値が範囲外の場合は、例外IndexErrorがスローされます。

x = np.array(1, 2], [3, 4], [5, 61, -1])]
array(3, 4],
[5, 6
)

x[np.array([)
x[np.array([3, 4])]
Traceback (most recent call last):
...
IndexError: index 3 is out of bounds for axis 0 with size 3

インデックスが、インデックス付け対象の配列の次元数と同じ数の整数配列で構成されている場合、インデックス付けは単純ですが、スライスとは異なります。

高度なインデックスは常に1つとしてブロードキャストされ、反復されます。

result[i_1, ..., i_M] == x[ind_1[i_1, ..., i_M], ind_2[i_1, ..., i_M],
..., ind_N[i_1, ..., i_M]]

結果として得られる形状は、(ブロードキャストされた)インデックス配列の形状と同一であることに注意してください。インデックスを同じ形状にブロードキャストできない場合は、例外が発生します。ind_1, ..., ind_NIndexError: shape mismatch: indexing arrays could not be broadcast together with shapes...

多次元インデックス配列を用いたインデックス付けは、あまり一般的ではない使い方ですが、許可されており、いくつかの問題には役立ちます。まずは、最も単純な多次元の場合から始めましょう。

y = np.arange(35).reshape(5, 7)
y
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, 30, 31, 32, 33, 34
)

y[np.array([0, 2, 4]), np.array([0, 1, 2])]
array([ 0, 15, 30])

この場合、インデックス配列の形状が一致し、インデックス付け対象の配列の各次元に対応するインデックス配列が存在する場合、結果の配列はインデックス配列と同じ形状になり、値はインデックス配列の各位置に対応するインデックスセットに対応します。この例では、両方のインデックス配列の最初のインデックス値は 0 なので、結果の配列の最初の値は です。次の値は、最後の値は です。y[0, 0]y[2, 1]y[4, 2]

インデックス配列の形状が異なる場合、同じ形状にブロードキャストしようと試みられます。同じ形状にブロードキャストできない場合は、例外が発生します。

y[np.array([0, 2, 4]), np.array([0, 1])]
Traceback (most recent call last):
...
IndexError: shape mismatch: indexing arrays could not be broadcast
together with shapes (3,) (2,)

ブロードキャスト機構により、インデックス配列を他のインデックスのスカラー値と組み合わせることが可能になります。その結果、スカラー値はインデックス配列の対応するすべての値に使用されます。

y[np.array([0, 2, 4]), 1]
array([ 1, 15, 29])

さらに複雑なレベルに進むと、インデックス配列を使って配列を部分的にインデックス付けすることも可能です。このような場合に何が起こるかを理解するには、少し考える必要があります。たとえば、y に 1 つのインデックス配列だけを使用する場合:

その結果、インデックス配列の各値がインデックス対象の配列から 1 行を選択する新しい配列が構築され、結果として得られる配列は、結果の形状 (インデックス要素の数、行のサイズ) を持ちます。

一般的に、結果として得られる配列の形状は、インデックス配列の形状(またはすべてのインデックス配列がブロードキャストされた形状)と、インデックス付けされている配列内の未使用の次元(インデックス付けされていない次元)の形状を連結したものになります。

各行から特定の要素を選択する必要があります。行インデックスは であり 、列インデックスは対応する行から選択する要素を指定します。ここでは です。これら両方を組み合わせることで、高度なインデックス付けを使用してタスクを解決できます。[0, 1, 2][0, 1, 0]

x = np.array(1, 2], [3, 4], [5, 6)
x0, 1, 2], [0, 1, 0

array([1, 4, 5])

上記の基本的なスライスと同様の動作を実現するには、ブロードキャストを使用できます。この関数は、ix_ブロードキャストに役立ちます。これは例で説明すると最もよく理解できます。

4x3配列から、高度なインデックスを使用して角の要素を選択する必要があります。つまり、列が のいずれかで、行が のいずれかであるすべての要素を選択する必要があります。高度なインデックスを使用するには、すべての要素を明示的に選択する必要があります。前述の方法を使用すると、次のように記述できます。[0, 2][0, 3]

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

rows = np.array(0, 0],
[3, 3
,
dtype=np.intp)
columns = np.array(0, 2],
[0, 2
rows, columns]
array(0, 2],
[ 9, 11
,
dtype=np.intp)
x[)

しかし、上記のインデックス配列は単に繰り返されるだけなので、ブロードキャスト(などの比較操作 )を使用してこれを簡略化できます。rows[:, np.newaxis] + columns

:, np.newaxis]
array(0],
[3
:, np.newaxis], columns]
array(0, 2],
[ 9, 11
rows = np.array([0, 3], dtype=np.intp)
columns = np.array([0, 2], dtype=np.intp)
rows[)
x[rows[)

この放送は、以下の関数を使用しても実現できますix_

np.ix_(rows, columns)]
array(0, 2],
[ 9, 11
x[)

なお、このnp.ix_呼び出しがない場合、対角線上の要素のみが選択されます。

x[rows, columns]
array([ 0, 11])

この違いこそが、複数の高度なインデックスを用いたインデックス作成において最も重要な点である。

高度なインデックス付けが役立つ実際の例として、画像の値を RGB トリプルにマッピングして表示するカラー ルックアップ テーブルが挙げられます。ルックアップ テーブルの形状は (nlookup, 3) とすることができます。形状が (ny, nx) で dtype=np.uint8 (または値がルックアップ テーブルの範囲内であれば任意の整数型) の画像を使用してこのような配列にインデックス付けすると、各ピクセル位置に RGB 値のトリプルが関連付けられた形状 (ny, nx, 3) の配列が得られます。

ブール配列のインデックス付け

この高度なインデックス付けは、obj がブール型の配列オブジェクトである場合に発生します。これは、比較演算子から返される可能性があります。単一のブール型インデックス配列は、実質的に と同じです。x[obj.nonzero()]ここで、 は、上記のように、objの要素を示す整数インデックス配列のobj.nonzero()タプル (長さ ) を返します。ただし、 の場合の方が高速です。obj.ndimTrueobj.shape == x.shape

の場合、objの値 に対応するx の要素で埋められた 1 次元配列が返されます。検索順序は行優先、C スタイルになります。obj の形状がx対応する次元と一致しない場合、それらの値がまたは で あるかどうかに関わらず、インデックス エラーが発生します。obj.ndim == x.ndimx[obj]TrueTrueFalse

この機能の一般的な使用例としては、目的の要素値をフィルタリングすることが挙げられます。例えば、配列から次の条件を満たさないすべてのエントリを選択したい場合などが考えられますnumpy.nan

x = np.array(1., 2.], [np.nan, 3.], [np.nan, np.nan)
x[~np.isnan(x)]
array([1., 2., 3.])

または、すべての負の要素に定数を加えたい場合:

x = np.array([1., -1., -2., 3])
x[x < 0] += 20
x
array([ 1., 19., 18., 3.])

一般に、インデックスにブール配列が含まれている場合、結果は、obj.nonzero()同じ位置に挿入し、上記で説明した整数配列インデックス機構を使用した場合と同じになります。 は と同等です 。x[ind_1, boolean_array, ind_2]x[(ind_1,) + boolean_array.nonzero() + (ind_2,)]

ブール配列が1つだけで、整数インデックス配列が存在しない場合は、処理は簡単です。注意すべき点は、ブールインデックスが扱うべき次元数と完全に一致するようにすることだけです。

一般に、ブール配列の次元数がインデックス付け対象の配列の次元数より少ない場合、これは と同等であり、つまり、x は b でインデックス付けされ、x のランクを埋めるのに必要な数だけ続きます。したがって、結果の形状は、ブール配列の True 要素の数を含む 1 つの次元と、インデックス付け対象の配列の残りの次元で構成されます。x[b, ...]:

:, 5]]
array(21, 22, 23, 24, 25, 26, 27],
[28, 29, 30, 31, 32, 33, 34
x = np.arange(35).reshape(5, 7)
b = x > 20
b[:, 5]
array([False, False, False, True, True])
x[b[)

ここでは、インデックス付き配列から4行目と5行目が選択され、結合されて2次元配列が作成されます。

配列から、合計が2以下のすべての行を選択します。

x = np.array(0, 1], [1, 1], [2, 2rowsum <= 2, :]
array(0, 1],
[1, 1
)

rowsum = x.sum(-1)
x[)

複数のブール型インデックス配列、またはブール型と整数型インデックス配列を組み合わせる場合、以下の例えを用いると最もよく理解できます obj.nonzero()。この関数はix_ ブール型配列もサポートしており、問題なく動作します。

ブールインデックスを使用して、合計が偶数になるすべての行を選択します。同時に、0列目と2列目を高度な整数インデックスで選択する必要があります。ix_この操作は、以下の関数を使用して実行できます。

x = np.array( 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11
np.ix_(rows, columns)]
array(3, 5],
[ 9, 11
)

rows = (x.sum(-1) % 2) == 0
rows
array([False, True, False, True])
columns = [0, 2]
x[)

このnp.ix_呼び出しがない場合、対角線上の要素のみが選択されます。

または、np.ix_(整数配列の例と比較すると)

:, np.newaxis], columns]
array(3, 5],
[ 9, 11
rows = rows.nonzero()[0]
x[rows[)

形状が(2, 3)で4つのTrue要素を持つ2次元ブール配列を使用して、形状が(2, 3, 5)の3次元配列から行を選択すると、形状が(4, 5)の2次元配列が得られます。

高度なインデックスと基本的なインデックスを組み合わせる

:インデックスにスライス( )、省略記号(...)、または()が少なくとも1つある場合newaxis (または配列の次元数が高度なインデックスの数よりも多い場合)、動作はより複雑になる可能性があります。これは、高度なインデックス要素ごとにインデックス結果を連結するようなものです。

最も単純なケースでは、単一の高度なインデックスとスライスが組み合わされています。例:

0, 2, 4]), 1:3]
array(1, 2],
[15, 16],
[29, 30
y = np.arange(35).reshape(5,7)
y[np.array([)

実際には、スライス操作とインデックス配列操作は独立しています。スライス操作はインデックス1と2の列(つまり2番目と3番目の列)を抽出し、続いてインデックス配列操作がインデックス0、2、4の行(つまり1番目、3番目、5番目の行)を抽出します。これは以下と同等です。

0, 2, 4]), :]
array(1, 2],
[15, 16],
[29, 30
y[:, 1:3][np.array([)

例えば、単一の高度なインデックスでスライスを置き換えることができ、結果の配列は同じになります。ただし、これはコピーであり、メモリレイアウトが異なる可能性があります。可能な場合はスライスを使用する方が望ましいです。例:

x = np.array( 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11
1:2, 1:3]
array(4, 5
1, 2]]
array(4, 5)

x[)
x[1:2, [)

複数の高度なインデックスの組み合わせを理解する最も簡単な方法は、結果として得られる形状を考えることかもしれません。インデックス操作には、基本インデックス(整数を除く)によって定義される部分空間と、高度なインデックス部分から得られる部分空間の2つの部分があります。インデックスの組み合わせには、次の2つのケースを区別する必要があります。

  • 高度なインデックスはスライス、Ellipsisまたは で区切られますnewaxis。たとえば、。x[arr1, :, arr2]

  • 高度なインデックスはすべて隣り合っています。たとえば、はこの点において高度なインデックスではありませんが、 は そうではありません。x[..., arr1, arr2, :] x[arr1, :, 1]1

最初のケースでは、高度なインデックス操作によって得られた次元が結果配列の先頭に配置され、その後に部分空間の次元が配置されます。2番目のケースでは、高度なインデックス操作による次元は、元の配列と同じ位置に結果配列に挿入されます(後者のロジックにより、単純な高度なインデックス操作はスライス操作と全く同じように動作します)。

x.shape(10, 20, 30) で、indが (2, 5, 2) 型のインデックスintp配列であるとすると、(20,) 型のサブスペースが (2, 5, 2) 型のブロードキャストインデックスサブスペースに置き換えられたため、の形状は (10, 2, 5, 2, 30) になります。i, j, k を(2, 5, 2) 型のサブスペースでループさせる と、 となります。この例では、 と同じ結果になります。result = x[..., ind, :]result[..., i, j, k, :] = x[..., ind[i, j, k], :]x.take(ind, axis=-2)

x.shapeを (10, 20, 30, 40, 50) とし、とind_1 をind_2形状 (2, 3, 4) にブロードキャストできるとします。すると、 の 形状は (10, 2, 3, 4, 40, 50) になります。これは、X の (20, 30) 形状の部分空間が、インデックスの (2, 3, 4) 部分空間に置き換えられたためです。しかし、 の 形状は (2, 3, 4, 10, 30, 50) になります。これは、インデックス部分空間にドロップする明確な場所がないため、先頭に追加されるためです。 を使用すると、部分空間を 任意の場所に移動できます。この例は では再現できないことに注意してください。x[:, ind_1, ind_2]x[:, ind_1, :, ind_2].transpose()take

スライスは、ブロードキャストされたブールインデックスと組み合わせることができます。

フィールドアクセス

関連項目

構造化配列

ndarrayオブジェクトが構造化配列の場合 、配列のフィールドには、文字列をインデックスとして使用して、辞書のようにアクセスできます。

インデックス付けを行うと、配列に対してx['field-name']新しいビューが返されます。このビューは、 xと同じ形状(フィールドがサブ配列の場合を除く)ですが、データ型が異なりx.dtype['field-name']、指定されたフィールド内のデータの一部のみを含みます。また、 レコード配列のスカラー値もこの方法で「インデックス付け」できます。

構造化配列へのインデックス付けは、フィールド名のリストを使用して行うこともできます。例: 。NumPy 1.16 以降では、これは指定されたフィールドのみを含むビューを返します。NumPy の以前のバージョンでは、コピーが返されていました。複数フィールドのインデックス付けの詳細については、ユーザーガイドの構造化配列のセクションを参照してください。x'field-name1', 'field-name2'

アクセスされたフィールドがサブ配列の場合、サブ配列の次元が結果の形状に追加されます。例:

x = np.zeros((2, 2), dtype=[('a', np.int32), ('b', np.float64, (3, 3))])
x['a'].shape
(2, 2)
x['a'].dtype
dtype('int32')
x['b'].shape
(2, 2, 3, 3)
x['b'].dtype
dtype('float64')

フラットイテレータのインデックス付け

x.flat配列全体を反復処理するイテレータを返します(C言語の連続スタイルで、最後のインデックスが最も速く変化します)。選択オブジェクトがタプルでない限り、このイテレータオブジェクトは、基本的なスライスまたは高度なインデックスを使用してインデックス付けすることもできます。これは、がx.flat1次元ビューであるという事実から明らかです。1次元のCスタイルフラットインデックスを使用した整数インデックス付けに使用できます。したがって、返される配列の形状は、整数インデックス付けオブジェクトの形状になります。

インデックス付き配列に値を割り当てる

前述のとおり、単一のインデックス、スライス、インデックスとマスク配列を使用して、配列のサブセットを選択して値を割り当てることができます。インデックス付き配列に割り当てられる値は、形状が一致している必要があります(インデックスが生成する形状と同じ形状であるか、またはブロードキャスト可能である必要があります)。たとえば、スライスに定数を割り当てることは可能です。

x = np.arange(10)
x[2:7] = 1

または適切なサイズの配列:

x[2:7] = np.arange(5)

上位型を下位型に代入する場合(例えば、浮動小数点数を整数に代入する場合)、あるいは例外が発生する場合(例えば、複素数を浮動小数点数や整数に代入する場合)には、代入によって変更が生じる可能性があることに注意してください。

x[1] = 1.2
x[1]
1
x[1] = 1.2j
Traceback (most recent call last):
...
TypeError: can't convert complex to int

配列やマスクのインデックスなどの参照とは異なり、代入は常に配列内の元のデータに対して行われます(実際、それ以外の方法は意味をなしません!)。ただし、一部の操作は、単純に期待する通りに動作しない場合があることに注意してください。次の例は、しばしば人々を驚かせます。

x = np.arange(0, 50, 10)
x
array([ 0, 10, 20, 30, 40])
x[np.array([1, 1, 3, 1])] += 1
x
array([ 0, 11, 20, 31, 40])

人々は最初の位置の値が3ずつ増加すると予想しますが、実際には1ずつしか増加しません。その理由は、元の配列から新しい配列(一時配列として)が抽出され、その一時配列に1、1、3、1という値が格納され、その後、その一時配列が元の配列に代入されるためです。したがって、最初の位置の配列の値は3回増加するのではなく、3回代入されることになります。x[1] + 1x[1]

プログラム内で可変数のインデックスを扱う

インデックス構文は非常に強力ですが、インデックスの数が可変の場合には制限があります。たとえば、可能な次元数ごとに特別なコードを記述することなく、さまざまな次元数の引数を処理できる関数を作成したい場合、どうすればよいでしょうか?インデックスにタプルを指定すると、そのタプルはインデックスのリストとして解釈されます。例:

z = np.arange(81).reshape(3, 3, 3, 3)
indices = (1, 1, 1, 1)
z[indices]
40

つまり、コードを使って任意の数のインデックスのタプルを作成し、それをインデックス内で使用することができます。

Pythonでは、slice()関数を使用してプログラム内でスライスを指定できます。例:

indices = (1, 1, 1, slice(0, 2)) # same as [1, 1, 1, 0:2]
z[indices]
array([39, 40])

同様に、省略記号はEllipsisオブジェクトを使用してコードで指定することもできます。

indices]
array(28, 31, 34],
[37, 40, 43],
[46, 49, 52
indices = (1, Ellipsis, 1) # same as [1, ..., 1]
z[)

このため、この np.nonzero()関数は常にインデックス配列のタプルを返すので、その出力をインデックスとして直接使用することが可能です。

タプルは特殊な扱いを受けるため、リストのように自動的に配列に変換されることはありません。例を挙げると次のようになります。

z1, 1, 1, 1 # produces a large array
array([[[[27, 28, 29],
[30, 31, 32], ...
z[(1, 1, 1, 1)] # returns a single value
40

詳細メモ

以下は、日々の索引作成には重要ではないものの、詳細なメモです(順不同)。

  • NumPy のネイティブなインデックス型は でありintp、デフォルトの整数配列型とは異なる場合があります。intpは、あらゆる配列を安全にインデックス付けするのに十分な最小のデータ型です。高度なインデックス付けでは、他の型よりも高速になる場合があります。

  • 高度な課題においては、一般的に反復順序は保証されません。つまり、ある要素が複数回設定された場合、最終結果を予測することはできません。

  • 空の(タプル)インデックスは、0次元配列への完全なスカラーインデックスです。 は、 が0次元の場合はスカラーx[()]を返し、それ以外の場合はビューを返します。一方、 は常にビューを返します。xx[...]

  • インデックスに0次元配列が存在しそれが完全な整数インデックスである場合、結果は0次元配列ではなくスカラー値になります。(高度なインデックス機能は有効になりません。)

  • 省略記号(...)が存在してもサイズが指定されていない場合(つまり、ゼロを置き換える場合 :)、結果は常に配列になります。高度なインデックスが存在しない場合はビュー、それ以外の場合はコピーになります。

  • ブール配列における等価nonzero性は、ゼロ次元ブール配列には当てはまりません。

  • 高度なインデックス操作の結果に要素がなく、個々のインデックスが範囲外である場合、例外がIndexError発生するかどうかは未定義です (たとえば、範囲外の場合)。x], [123123

  • 代入時に型変換エラーが発生した場合(例えば、文字列のシーケンスを使用して数値配列を更新する場合など)、代入先の配列は予期しない部分更新状態になる可能性があります。ただし、その他のエラー(例えば、範囲外のインデックスなど)が発生した場合は、配列は変更されません。

  • 高度なインデックス結果のメモリレイアウトは、各インデックス操作に合わせて最適化されており、特定のメモリ順序を想定することはできません。

  • サブクラス(特に形状を操作するサブクラス)を使用する場合、デフォルトのndarray.__setitem__動作では基本的なインデックス__getitem__付けは 行われますが、高度なインデックス付けは行われません。このようなサブクラスの場合、基底クラスのndarrayビューを使用してデータを呼び出す方が望ましい場合があります。サブクラスがビューを返さない場合は、この操作を行う必要があります。ndarray.__setitem____getitem__

シェアボタン: このページをSNSに投稿するのに便利です。

コメント

返信元返信をやめる

※ 悪質なユーザーの書き込みは制限します。

最新を表示する

NG表示方式

NGID一覧