NumPyの使い方(3) インデックス、スライス
NumPyのインデックス、スライスについて。
1次元配列のインデックス、スライス
値の参照:python組み込みのlistと同様
値の代入:まとめて同じ値が代入(ブロードキャスト)
import numpy as np # 値の参照、代入 a1 = np.arange(1, 10) print(a1) # [1 2 3 4 5 6 7 8 9] print(a1[3]) # 4 print(a1[3:6]) # [4 5 6] a1[3:6] = 0 # すべての要素の0を代入 print(a1) # [1 2 3 0 0 0 7 8 9]
・[注意]部分配列はコピーではなくビューになる。つまり、
参照して作成した部分配列の要素を変更すると、参照元のndarrayも変更される。
a1 = np.arange(1, 10) print(a1) # [1 2 3 4 5 6 7 8 9] # インデックス参照で新たな変数を作り代入した場合は元は保存 x = a1[8] x = 0 print(a1) # [1 2 3 4 5 6 7 8 9] # スライス参照で新たな部分配列を作り代入した場合は元も変更 a2 = a1[3:6] a2[:] = 10 print(a2) # [10 10 10] print(a1) # [ 1 2 3 10 10 10 7 8 9] a2[0] = 20 print(a2) # [20 10 10] print(a1) # [ 1 2 3 20 10 10 7 8 9] # built-inのlist型とは挙動が異なる list1 = list(range(1, 10)) list1[3:6] = [0] print(list1) # [1, 2, 3, 0, 7, 8, 9] # 元のndarrayを保存したいときはcopy()メソッドを使う。 a2 = a1[0:3].copy()
2次元配列のインデックス
・a2[1][0] arr2の1行目0列目の要素を指定
・a2[1, 0] 同義
a2 = np.array([[1, 2, 3], [4, 5, 6]]) print(a2) # [[1 2 3] # [4 5 6]] print(a2.shape) # (2, 3) print(a2[1][0]) # 4 print(a2[1, 0]) # 4
3次元配列のインデックス
a3[0][1][2] a3の0枚目の1行目の2列目
a3 = np.array([[[1, 2, 3], [4, 5, 6]],[[7, 8, 9], [10, 11, 12]]]) print(a3) # [[[ 1 2 3] # [ 4 5 6]] # # [[ 7 8 9] # [10 11 12]]] print(a3.shape) # (2, 2, 3) print(a3[0]) # [[1 2 3] # [4 5 6]] print(a3[0, 1]) #[4 5 6] print(a3[0, 1, 2]) # 6
多次元配列のスライス参照
・スライスすると配列の次元は変わらない。
・(数値で)インデックス参照すると次元が1つ減る。
3次元配列のa3について、 スライス 部分配列 a3[1:] 3次元 a3[1] 2次元 a3[1:, 1:] 3次元 a3[1, 1:] 2次元 a3[1, 1] 1次元 a3[1, 1, 1] 0次元、つまり値
# 3次元配列を用意 a3 = np.array([[[1, 2, 3], [4, 5, 6]],[[7, 8, 9], [10, 11, 12]]]) print(a3) # [[[ 1 2 3] # [ 4 5 6]] # # [[ 7 8 9] # [10 11 12]]] print(a3.shape) # (2, 2, 3) print(a3[1:].ndim) # 3 print(a3[1].ndim) # 2 print(a3[1:, 1:].ndim) # 3 print(a3[1, 1:].ndim) # 2 print(a3[1, 1].ndim) # 1 print(a3[1, 1, 1].ndim) # 0 print(a3[1:]) # [[[ 7 8 9] # [10 11 12]]] print(a3[1]) # [[ 7 8 9] # [10 11 12]] print(a3[1:, 1:]) # [[[10 11 12]]] print(a3[1, 1:]) # [[10 11 12]] print(a3[1, 1]) # [10 11 12] print(a3[1, 1, 1]) # 11
ブールインデックス
bool値がTrueとなるものだけを選ぶことができる。
ビュー(参照)ではなく、コピーとなる。
rgb = np.array(["r", "g", "b", "r", "g", "b"]) print(rgb == "r") # [ True False False True False False] print(rgb[rgb == "r"]) #['r' 'r'] print(rgb[rgb != "r"]) #['g' 'b' 'g' 'b']
rgb = np.array(["r", "g", "b", "r", "g", "b"]) # 乱数の初期化 np.random.seed(1) # 0~255までの乱数で6行4列の配列を作る data = np.random.randint(0, 256, size=(6, 4)) print(data) # [[ 37 235 140 72] # r # [255 137 203 133] # g # [ 79 192 144 129] # b # [204 71 237 252] # r # [134 25 178 20] # g # [254 101 146 212]] # b print(data[rgb == "r"]) # rgbがrの行だけを抽出 # [[ 37 235 140 72] # [204 71 237 252]] print(data[rgb != "r"]) # rgbがr以外の行を抽出(1) # [[255 137 203 133] # [ 79 192 144 129] # [134 25 178 20] # [254 101 146 212]] # 真偽値のbit反転でも書ける print(~(rgb == "r")) # [False True True False True True] print(data[~(rgb == "r")]) # rgbがr以外の行を抽出(2) # [[255 137 203 133] # [ 79 192 144 129] # [134 25 178 20] # [254 101 146 212]] print(data[rgb == "r", 0:2]) # rbgがrの行の0~1列目の要素 # [[ 37 235] # [204 71]] print(data[rgb == "r", 0]) # rbgがrの行の0列目の要素 # [ 37 204] 1次元の配列は横向き(横ベクトル)で表示 data[data < 100] = 0 # 100未満のすべての要素を0にする。 print(data) # [[ 0 235 140 0] # [255 137 203 133] # [ 0 192 144 129] # [204 0 237 252] # [134 0 178 0] # [254 101 146 212]]
ファンシーインデックス
複数のインデックス参照を整数配列(list, ndarrayなど)で指定する。
スライスと違い、元データのコピーを返す。
list1 = [[i+j for i in range(5)] for j in range(0, 50, 10)] a1 = np.array(list1) print(a1) # [[ 0 1 2 3 4] # [10 11 12 13 14] # [20 21 22 23 24] # [30 31 32 33 34] # [40 41 42 43 44]] print(a1[1]) # [10 11 12 13 14] 1列目 print(a1[3]) # [30 31 32 33 34] 3列目 #インデック指定であることを表す[]の中にlistの[] >>> 2重[[]] print(a1[[1, 3, 1]]) #1列目、3列目、1列目の順に参照 # [[10 11 12 13 14] # [30 31 32 33 34] # [10 11 12 13 14]] print(a1[[-1, -2, -3]]) #後ろから1列目、2列目、3列目 # [[40 41 42 43 44] # [30 31 32 33 34] # [20 21 22 23 24]] # 5行10列の配列の準備 a2 = np.arange(50).reshape(5, 10) print(a2) # [[ 0 1 2 ..., 7 8 9] # [10 11 12 ..., 17 18 19] # [20 21 22 ..., 27 28 29] # [30 31 32 ..., 37 38 39] # [40 41 42 ..., 47 48 49]] print(a2[[0, 1, 2, 3],[9, 8, 7, 6]]) # [ 9 18 27 36] print(a2[range(5), range(5)]) # [ 0 11 22 33 44] print(a2[[1, 3]][:, range(1, 10, 2)]) # 10の位も1の位も奇数の要素 # [[11 13 15 17 19] # [31 33 35 37 39]] # np.ix_(list1, list2)でも同義 print(a2[np.ix_([1, 3], range(1, 10, 2))]) # [[11 13 15 17 19] # [31 33 35 37 39]]
take()とput()
take()は指定されたindexから値を取得。
put()は指定されたindexに値を代入。
a1 = np.arange(0, 100, 10) print(a1) # [ 0 10 20 30 40 50 60 70 80 90] print(a1.take([1, 3, 5])) # [10 30 50] a1.put([1, 3, 5], [0, 0, 0]) print(a1) # [ 0 0 20 0 40 0 60 70 80 90] a2 = np.arange(6).reshape(2, 3) print(a2) # [[0 1 2] # [3 4 5]] print(a2.take([1], axis=1)) # [[1] # [4]] print(a2.take([1], axis=0)) # [[3 4 5]] print(a2.take([1])) # axis指定なしだと1d化 # [1] print(a2) a2.put([4, 5], 10) # flatten後のindexを指定 print(a2) # [[ 0 1 2] # [ 3 10 10]]