【Python初心者向け】NumPyの使い方を徹底解説!その2

【Python初心者向け】辞書(dict)の使い方を徹底解説!

PytonのNumPyの使い方その1では、初期化と要素の追加・削除について解説しました。

【Python初心者向け】NumPyの使い方を徹底解説!その1

ここからはndarrayの要素へのアクセスと演算について解説します。

リストの要素にアクセスする

まずはndarrayの要素へアクセスする方法を見ていきましょう。

ここでは多次元リストの場合を中心に解説しています。

要素の参照

要素の参照は通常のリストと同じようにインデックス番号を使います。今回は2次元リストなので、1つの要素にアクセスしたい場合は2つのインデックス番号を指定します。

import numpy as np

np_list = np.array(list(range(1, 10))).reshape(3, 3)
print(np_list)
print(np_list[1]) #行を出力
print(np_list[2][2]) #要素を出力
print(np_list[2, 2]) #こういうアクセス方法もある
[[1 2 3]
[4 5 6]
[7 8 9]]

[4 5 6]

9

9

要素の更新

要素の更新も参照と同じくインデックス番号を使います。

import numpy as np

np_list = np.array(list(range(1, 10))).reshape(3, 3)
print(np_list)
np_list[1, 1] = 10
print(np_list)
np_list[2] = [11, 12, 13] #行を更新する
print(np_list)
[[1 2 3]
[4 5 6]
[7 8 9]]

[[ 1 2 3]
[ 4 10 6]
[ 7 8 9]]

[[ 1 2 3]
[ 4 10 6]
[11 12 13]]

多次元リストをスライスする

スライスとはリストの一部分だけを切り出すことです。

スライスの詳細はこちら↓

【Python初心者向け】リスト(list)の使い方を徹底解説!〜リストのあれこれ〜

ndarrayの多次元リストの場合は[行の開始位置:行の終了位置, 列のスライス開始位置:列のスライス終了位置]と指定することで、行と列に対してスライスが可能です。

import numpy as np

np_list = np.array(list(range(1, 10))).reshape(3, 3)
print(np_list[:, :]) #全て
print(np_list[1:, :]) #2行目以降
print(np_list[:, 1:]) #2列目以降
print(np_list[:2, :2]) #2行目までかつ2列目まで
print(np_list[1:2, 1:2]) #真ん中の要素
[[1 2 3]
[4 5 6]
[7 8 9]]
[[4 5 6]
[7 8 9]]
[[2 3]
[5 6]
[8 9]]
[[1 2]
[4 5]]
[[5]]

全ての要素を順番に取り出す

多次元リストの全ての要素を取得する場合はfor..inをネストするのが直感的です。

import numpy as np

np_list = np.array(list(range(1, 5))).reshape(2, 2)
for items in np_list:
  for item in items:
    print(item)
1
2
3
4

しかし、forのネストはソースコードが読みにくくなりがちです。

NumPyではndenumerate()という関数が用意されています。ndenumerate()を使って要素を取り出すと、要素の他に行と列の情報がタプルで付与されます。

import numpy as np

np_list = np.array(list(range(1, 5))).reshape(2, 2)
for i, item in np.ndenumerate(np_list):
  print(i, item)
(0, 0) 1
(0, 1) 2
(1, 0) 3
(1, 1) 4

条件に合った要素のみ取得する

リスト内で条件に合った要素のみを抽出して取得することもできます。条件式には比較演算子や論理演算子が使えます。多次元リストの場合は条件で抽出すると1次元リストになります。

import numpy as np

np_list = np.array(list(range(1, 10))).reshape(3, 3)
print(np_list[np_list < 5])
print(np_list[np_list >= 5])
[1 2 3 4]
[5 6 7 8 9]

また、論理演算は「and」「or」「not」の代わりに「&」「|」「~」を使います。

import numpy as np

np_list = np.array(list(range(1, 10))).reshape(3, 3)
print(np_list[(np_list >= 3) & (5 >= np_list)]) #3以上5以下
print(np_list[(np_list == 1) | (np_list > 6)]) #1または6より上
print(np_list[~(np_list%3 == 0)]) #3の倍数以外
[3 4 5]
[1 7 8 9]
[1 2 4 5 7 8]

条件に合う要素を一括更新する

条件を指定して一括で要素を更新することもできます。下の例では偶数を0、奇数を1に置き換えています。

import numpy as np

np_list = np.array(list(range(1, 17))).reshape(4, 4)
np_list[np_list%2 == 0] = 0
np_list[np_list%2 == 1] = 1
print(np_list)
[[1 0 1 0]
[1 0 1 0]
[1 0 1 0]
[1 0 1 0]]

NumPyの演算

ndarrayは通常のリストにはない優れた機能がいくつもあり、化学計算や機械学習に使われています。一つずつ見ていきましょう。

四則演算

要素が数値のリストのときは、リスト同士で四則演算することができます。

import numpy as np

A = [[3, 6], [2, 5]]
B = [[9, 1], [4, 7]]
C = A + B
print(C) #通常のリストの場合は結合になる

A_n = np.array(A)
B_n = np.array(B)
C_n = A_n + B_n
print(C_n) #ndarrayの場合は加算される
[[3, 6], [2, 5], [9, 1], [4, 7]]


[[12 7]
[ 6 12]]

引き算、掛け算、割り算も同様に計算できます。

import numpy as np

A = np.array([[3, 6], [2, 5]])
B = np.array([[9, 1], [4, 7]])
C = A - B
D = A * B
E = A / B
print(C)
print(D)
print(E)
[[-6 5]
[-2 -2]]

[[27 6]
[ 8 35]]

[[ 0.33333333 6. ]
[ 0.5 0.71428571]]

行列数が異なるリスト同士の計算

行列数が異なる場合は足りない行や列を補って計算します(ブロードキャストと言います)

import numpy as np

A = np.array([[1, 2], [3, 4]])
B = np.array([10, 20])
C = A + B
print(C)
[[11 22]
[13 24]]

上の例ではAが2行2列に対してBが1行2列なので、Bの行列が1行足りていません。

この場合はBの行を複製して補った後に計算しています。

また、列が足りない場合も同様にブロードキャストされて計算されます。

import numpy as np

A = np.array([1, 2, 3, 4, 5, 6]).reshape(2, 3)
B = np.array([10, 20]).reshape(2, 1)
C = A + B
print(C)
[[11 12 13]
[24 25 26]]

合計・最小値・最大値

合計はsum()、最小値はmin()、最大値はmax()で求めることができます。

列単位での計算は引数に0を、行単位での計算は引数に1を指定します。

import numpy as np

A = np.array(list(range(1, 10))).reshape(3, 3)
print(A)

sum = A.sum() #全要素の合計
print(sum)

sum_row = A.sum(0) #列の合計
print(sum_row)

sum_col = A.sum(1) #行の合計
print(sum_col)

min = A.min() #最小値
print(min)

max = A.max() #最大値
print(max)
[[1 2 3]
[4 5 6]
[7 8 9]]
45
[12 15 18]
[ 6 15 24]
1
9

算術平均・分散・標準偏差を計算する

算術平均はmean()、標準偏差はstd()、分散はvar()で計算できます。

import numpy as np

A = np.random.randint(0, 100, 30)
print(A)

print(np.mean(A)) #算術平均
print(np.std(A)) #標準偏差
print(np.var(A)) #分散
[12 19 10 3 66 55 10 48 84 93 26 69 30 40 68 25 99 7 68 51 53 18 61 5 60
85 91 77 73 41]
48.2333333333
29.1521106535
849.845555556

内積の計算

行列の内積計算はdot()を使います。内積を計算するには、左右の行列の行数が等しくないとできません。

import numpy as np

A = np.array([3, 2, 4, 5]).reshape(2, 2)
B = np.array([2, 6, 1, 4]).reshape(2, 2)
C = np.dot(A, B)
print(C)
[[ 8 26]
[13 44]]