NumPy 要素の参照
リストと同じようにスライスできる。
x = np.arange(10) x x[3] x[1:4] x[4:-1:2]
[0 1 2 3 4 5 6 7 8 9] 3 [1 2 3] [4 6 8]
多次元配列も多次元リストと同様
x = np.random.randint(1, 10, size=(4, 5)) x x[3] x[3][0]
[[4 6 5 7 6] [4 5 8 2 5] [9 3 8 5 7] [8 2 9 8 1]] [8 2 9 8 1] 8
配列はリストと異なり、,で区切って要素を参照できる。
x = np.random.randint(1, 10, size=(4, 5)) x x[0][1] x[0, 1] # 0行1列目 x[:, 1] # 1列目 x[0, :] # 0行目 x[0:3, 1:4] # 0~2行目まで取り出し、そのあと1~3列目まで x[::2,::2] # 各次元を1つ飛ばして参照
[[4 5 1 4 7] [4 5 6 7 4] [9 3 3 1 7] [6 8 5 5 2]] 5 5 [5 5 3 8] [4 5 1 4 7] [[5 1 4] [5 6 7] [3 3 1]] [[4 1 7] [9 3 7]]
スライスで取得したものはビューと呼ばれ、、元の配列と同じメモリ上のデータを参照している。気をつけなければいけないのは、ビューの要素を変更した場合、同じメモリ上のデータを参照している配列も変更されることになる。
x = np.random.randint(1, 10, size=(4, 5)) x y = x[:3, :3] y y[:, :] = 0 # yの要素を全て0にする y x
[[7 2 8 6 2] [4 3 6 2 7] [9 5 2 4 5] [5 4 7 7 9]] [[7 2 8] [4 3 6] [9 5 2]] [[0 0 0] [0 0 0] [0 0 0]] # ↓!? [[0 0 0 6 2] [0 0 0 2 7] [0 0 0 4 5] [5 4 7 7 9]]
これを解決するにはcopyメソッドを使用。
この返り値は部分配列のデータは新しくメモリ上にコピーされる。
z = x[:3, :3].copy() z z[:, :] = -5 z x
[[7 2 8] [4 3 6] [9 5 2]] [[-5 -5 -5] [-5 -5 -5] [-5 -5 -5]] # ↓影響無し [[0 0 0 6 2] [0 0 0 2 7] [0 0 0 4 5] [5 4 7 7 9]]
ファンシーインデックス参照という、整数要素のリストや配列を
インデックスに使う参照方法がある。
これははじめからコピーとして切り出すのでもとの配列に影響は無い。
x = np.random.randint(1, 10, size=(4, 4)) x # xの0番目と3行目の行から成る配列は x[[0, 3]] # 0行2列めと2行3列目の要素から成る配列は x[[0, 2], [2, 3]]
[[6 9 8 5] [2 9 5 5] [6 4 2 2] [5 2 3 1]] [[6 9 8 5] [5 2 3 1]] [8 2]