Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

NumPy:インデックスとスライス

配列の一部を取り出したり書き換えたりする操作をまとめる. セルオートマトン(P2-02)や拡散方程式(P2-03)では,注目するセルとその近傍を取り出すためにこれらを多用する.

import numpy as np

a = np.array([1, 2, 3])
b = np.array([6, 3.3, 1])
C = np.array([[1, 5, 6], [7, 8, 9], [4, 2, 3]])
D = np.array([[2.3, 4, 7.2], [7, 9, 1], [11, 2, 9]])

インデックス

位置(インデックス)を指定して1つの要素にアクセスする.インデックスは 0 から始まる.負の値は末尾から数える.

print("a[0]:", a[0])
print("末尾 a[-1]:", a[-1])
a[0]: 1
末尾 a[-1]: 3

2次元配列では,行・列の順にインデックスを与える.C[0] は0行目全体,C[0, 1] は0行1列の要素である.

print("0行目 C[0]:", C[0])
print("0行1列 C[0, 1]:", C[0, 1])
0行目 C[0]: [1 5 6]
0行1列 C[0, 1]: 5

スライス

スライス (slicing)は,start:stop:step の形で連続した範囲を取り出す操作である.stop は含まれない点に注意する.

print("b[0:2]:", b[0:2])  # 0 番目から 2 未満
print("b[::2]:", b[::2])  # 1 つおき
b[0:2]: [6.  3.3]
b[::2]: [6. 1.]

2次元配列では行と列それぞれにスライスを与えられる.

print("D の左上 2x2 ブロック:\n", D[0:2, 0:2])
print("0 列目全体 D[:, 0]:", D[:, 0])
D の左上 2x2 ブロック:
 [[2.3 4. ]
 [7.  9. ]]
0 列目全体 D[:, 0]: [ 2.3  7.  11. ]

ファンシーインデックス

ファンシーインデックス (fancy indexing)では,整数のリストを添字に渡して任意の行や列をまとめて選べる.

print("0,1 行目:\n", C[[0, 1]])
print("0,1 列目:\n", C[:, [0, 1]])
0,1 行目:
 [[1 5 6]
 [7 8 9]]
0,1 列目:
 [[1 5]
 [7 8]
 [4 2]]

行と列の両方をリストで指定する場合は,2段階に分けて書くと分かりやすい.

# 0,1 行かつ 0,1 列のブロック
print(C[[0, 1]][:, [0, 1]])
[[1 5]
 [7 8]]

ブールインデックス(条件による選択)

ブールインデックス (boolean indexing)では,真偽値の配列でマスクして条件を満たす要素だけを取り出せる.

print("C > 5:\n", C > 5)
print("5 より大きい要素:", C[C > 5])

# 条件を満たす要素だけ書き換える
C2 = np.copy(C)
C2[C2 > 5] = 0
print("5 超を 0 に:\n", C2)
C > 5:
 [[False False  True]
 [ True  True  True]
 [False False False]]
5 より大きい要素: [6 7 8 9]
5 超を 0 に:
 [[1 5 0]
 [0 0 0]
 [4 2 3]]

近傍の取り出し(応用)

セルオートマトンや拡散方程式では,あるセル [i, j] とその上下左右・周囲のセルをまとめて取り出す. ファンシーインデックスを使うと,端で反対側に回り込む周期境界条件 (periodic boundary condition)を簡潔に表現できる.

field = np.arange(16).reshape(4, 4)
print("field:\n", field)

# 中心 i=0, j=0 の 3x3 近傍(-1 で末尾に回り込む = 周期境界)
i, j = 0, 0
neighborhood = field[[i - 1, i, i + 1], :][:, [j - 1, j, j + 1]]
print("(0,0) の周期的 3x3 近傍:\n", neighborhood)
field:
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
(0,0) の周期的 3x3 近傍:
 [[15 12 13]
 [ 3  0  1]
 [ 7  4  5]]

field[[i-1, i, i+1], :] でまず3行を選び,続く [:, [j-1, j, j+1]] で3列を選ぶ. i-1-1 になると末尾の行を指すため,格子の端がトーラス状につながる.この考え方を P2-02・P2-03 で繰り返し使う.