概要
配列の要素や行・列の抽出などに関する操作。
準備として、以下の1次元、2次元配列を考える。
1 2 3 4 5 6 7 8 9 10 |
a1 = np.array([0, 1, 2, 3]) a2 = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) print(a1) print(a2)[0 1 2 3] # [0 1 2 3] # [[0 1 2] # [3 4 5] # [6 7 8]] |
要素の参照
1次元配列の要素の参照は、リストと同じ。
1 2 3 4 5 6 7 |
print(a1[0]) print(a1[-1]) print(a1[-2]) # 0 # 3 # 2 |
2次元配列の要素は、[行, 列]で指定。行・列の値の考え方は1次元配列の要素と同じ。
1 2 3 4 5 |
print(a2[1, 2]) print(a2[-1, -2]) # 5 # 7 |
行・列の参照
単一の行・列の参照
2次元配列の行の参照は、行番号を指定。
1 2 3 |
print(a2[0]) # [0 1 2] |
2次元配列の列の参照はややこしくて、[:,列番号]
で指定。1つ目の:
は行番号のプレースホルダーみたいなものか。
ただし、列を取り出した結果でも、1次元の配列になる。
1 2 3 |
print(a2[:,0]) # [0 3 6] |
直接列ベクトルで取り出したい場合は、[:,列番号:列番号+1]
で可能。
1 2 3 4 5 |
print(a2[:,2:3]) # [[2] # [5] # [8]] |
なお、1次元の配列にndarray.Tを作用させても、1次元配列のままで列ベクトルにはならない。
範囲を指定した行・列の参照
行の範囲を指定して、複数行の行列を返す。
1 2 3 |
print(a2[1:3]) # [0 3 6] |
列の範囲を指定する場合。
1 2 3 4 5 |
print(a2[:,1:3]) # [[1 2] # [4 5] # [7 8]] |
複数の行・列を指定した参照
連続しない複数の行を取り出した行列をつくるには、[行番号, 行番号, …]とする。
1 2 3 4 5 6 |
print(a2[[0,2,0,2]]) # [[0 1 2] # [6 7 8] # [0 1 2] # [6 7 8]] |
複数列を取り出す場合。
1 2 3 4 5 |
print(a2[:,[0,2,0,2]]) # [[0 2 0 2] # [3 5 3 5] # [6 8 6 8]] |
参照であることの注意
以上の操作で取り出された配列は、元の配列への参照を保っているため、その要素を変更すると元の配列の要素も変更される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
r = a2[0] c = a2[:,2] print(r) print(c) r[0] = -1 c[2] = -2 print(r) print(c) print(a2) # 取り出された行・列 # [0 1 2] # [2 5 8] # 変更された行・列 # [-1 1 2] # [ 2 5 -2] # 元の配列にも影響 # [[-1 1 2] # [ 3 4 5] # [ 6 7 -2]] |
元の配列に影響させたくない場合は、copy.copy()、copy.deepcopy()、np.copy()でオブジェクトをコピーする必要がある。
対角要素の取り出し
np.diag()で、2次元配列の対角要素を取り出した1次元配列が得られる。
ただし、その結果は書き込みできない。
1 2 3 |
d = np.diag(a2) print(d) # [0 4 8] d[0] = -1 # ValueError: assignment destination is read-only |
条件を指定した取り出し
配列に条件式を適用して、各要素が要件に合致していればTrue、合致していなければFalseを要素とする配列を返す。
1 2 3 4 5 |
print(a2%2 == 0) # [[ True False True] # [False True False] # [ True False True]] |
上で得られた配列を要素とすることで、条件に合致した要素のみを取り出した1次元配列を得る。
1 2 3 |
print(a2[a2%2 == 0]) # [0 2 4 6 8] |