今回はndarrayの要素の参照方法について詳しく紹介する。

1次元配列のインデックス参照

まずは1次元のndarrayからインデックス参照で値を取り出す方法を見ていく。

これはPython標準のリストと同じ動作なので容易く理解できるはずだ。

import numpy as np

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

arr[3] # 3
arr[1:3] # array([1, 2])

# Pythonのリストと違い、スライスにスカラー値を代入できる
arr[1:3] = 10
# array([ 0, 10, 10,  3,  4,  5,  6,  7,  8,  9])

なお、Pythonのリストと違う点として、スライスして切り出した一部は元のndarrayのコピーではなく参照をしているので、10行目のように値を代入すると元のndarrayに変更が反映される。

もう少し詳しく見てみよう。

import numpy as np

arr = np.arange(10)

arr2 = arr[2:5]
arr2 # array([2, 3, 4])

arr2[1] = 10

arr
# array([ 0,  1,  2, 10,  4,  5,  6,  7,  8,  9])

この例では、arr2にスライスした一部の要素を代入している。

そして8行目でarr2に対して変更を加えているが、参照元のarrにも変更が適用されていることが分かる。

なお、ndarrayのスライスを参照ではなくコピーしたい場合は、copyメソッドを使えばOKだ。

import numpy as np

arr = np.arange(10)

arr2 = arr[2:5].copy()
arr2 # array([2, 3, 4])

arr2[1] = 10

arr
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

arr2
# array([ 2, 10,  4])

多次元配列のインデックス参照

多次元のndarrayの場合、インデックス参照の方法が増える。

単純に階層的に参照する方法と、2次元配列を行列に見立てカンマ区切りで参照する方法があるのだ。

import numpy as np

arr_2d = np.array([
    [1, 2, 3],
    [4, 5, 6]
])

arr_2d[0][1] # 2
arr_2d[0, 1] # 2

カンマ区切りの参照は次元数に関わらず扱うことができる。

import numpy as np

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

arr_3d[0, 1, 1] # 5

なお、ここで参照している要素はあくまでビューとなるので、切り出した要素をコピーする場合は先述のcopyメソッドを使う必要がある。

多次元配列のスライシング

多次元配列でもスライス記法による要素の参照をおこなうことができる。

まずは2次元配列の例を見てみよう。

import numpy as np

arr_2d = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

arr_2d[:2]
# array([[1, 2, 3],
#       [4, 5, 6]])

[:2]と書かれたら、「2行目までを参照する」と覚えると分かりやすいだろう。

また、多次元配列ならではの記法として、以下のように複数のスライスを指定することもできる。

import numpy as np

arr_2d = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

arr_2d[:2, :1]
# array([[1],
#       [4]])

これは「2行目までを取りだし、それぞれの1列目までを参照する」ということだ。

また、インデックス参照とスライシングを組み合わせて利用することも可能だ。

import numpy as np

arr_2d = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

arr_2d[2, :1] # array([7])
arr_2d[:2, 1] # array([2, 5])

9行目は「3行目のみを取り出し、1列目までを参照する」、
10行目は「2行目までを取り出し、2列目のみを参照する」ということだ。

まとめ

多次元のndarrayのスライス記法は慣れないと取っ付きづらく感じてしまうが、Python独自の非常に有効な参照方法なので、ぜひ活用していきたい。