NumPy:配列のスライシングとインデックス指定

NumPy 配列から特定の要素を取り出すには、スライシングとインデックス指定を使います。Python のリストと似ていますが、多次元配列でより強力に使えます。

基本的なインデックス指定

1次元配列では、Python のリストと同じようにインデックスで要素を取得できます。

import numpy as np

a = np.array([10, 20, 30, 40, 50])

print(a[0])   # 10(先頭)
print(a[-1])  # 50(末尾)
print(a[2])   # 30

2次元配列では、[行, 列] の形式で指定します。

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

print(a[0, 0])  # 1(0行0列)
print(a[1, 2])  # 6(1行2列)
print(a[2, 1])  # 8(2行1列)

スライシング

コロン : を使って範囲を指定します。start:stop で start から stop の手前まで取得します。

a = np.array([10, 20, 30, 40, 50])

print(a[1:4])   # [20 30 40](インデックス1〜3)
print(a[:3])    # [10 20 30](先頭から3つ)
print(a[2:])    # [30 40 50](インデックス2以降)
print(a[::2])   # [10 30 50](1つ飛ばし)

2次元配列でも同様に使えます。

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

# 0〜1行目、1〜2列目
print(a[0:2, 1:3])
# [[2 3]
#  [6 7]]

# 全行、2列目以降
print(a[:, 2:])
# [[ 3  4]
#  [ 7  8]
#  [11 12]]

# 1行目のすべて
print(a[1, :])  # [5 6 7 8]
print(a[1])     # [5 6 7 8](同じ結果)

ファンシーインデックス

リストや配列で複数のインデックスを指定できます。これをファンシーインデックスと呼びます。

a = np.array([10, 20, 30, 40, 50])

# インデックス0, 2, 4の要素
print(a[[0, 2, 4]])  # [10 30 50]

2次元配列では、行と列それぞれにリストを渡します。

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

# (0,0), (1,1), (2,2) の要素(対角成分)
print(a[[0, 1, 2], [0, 1, 2]])  # [1 5 9]

ブールインデックス

条件式を使って要素を選択できます。

a = np.array([1, 5, 3, 8, 2, 9])

# 5より大きい要素
print(a[a > 5])  # [8 9]

# 偶数の要素
print(a[a % 2 == 0])  # [8 2]

条件を満たす要素だけを取り出せるので、データのフィルタリングに便利です。

# 条件に合う要素を書き換える
a = np.array([1, 5, 3, 8, 2, 9])
a[a > 5] = 0
print(a)  # [1 5 3 0 2 0]

スライスはビューを返す

スライスで取得した配列は、元の配列のビュー(参照)です。変更すると元の配列も変わります。

a = np.array([1, 2, 3, 4, 5])
b = a[1:4]
b[0] = 99
print(a)  # [ 1 99  3  4  5]

コピーが必要な場合は .copy() を使ってください。

a = np.array([1, 2, 3, 4, 5])
b = a[1:4].copy()
b[0] = 99
print(a)  # [1 2 3 4 5](変わらない)