Python - numpy - ndarray

公開日:2019-05-28 更新日:2019-05-28
[Python]

1. 概要

numpy の ndarray の使い方についてです。
ndarray は、既存の配列を拡張した配列で、単純に便利な配列として使えます。

例えば、各要素の値を3倍したい場合、普通の配列の場合はリスト内包表記で書きますが、 ndarray の場合は、単純に *3 とするだけで行えます。
import numpy as np

#普通の配列
ary    = [1,2,3,4,5]
ary1 = [v * 3 for v in ary]     #[3, 6, 9, 12, 15]

#ndarray
np_ary  = np.array([1,2,3,4,5])
np_ary2 = np_ary * 3            #[ 3  6  9 12 15]

numpy をインストールしていない場合は、Anacondaプロンプトで以下を実行してインストールしてください。
pip install numpy

2. 動画



3. ndarray の基本

ndarrayの生成、要素の追加、設定、取得、削除、要素数の取得、普通の配列に変換。
import numpy as np

#生成
np_ary = np.array([1,2,3,4,5])

#追加
np_ary2 = np.append(np_ary, [6,7,8,9,10])
print(np_ary2) #[ 1  2  3  4  5  6  7  8  9 10]

#設定
np_ary2[0] = 999

#取得
print(np_ary2[0]) #999

#要素数の取得
print(len(np_ary2)) #10

#削除
np_ary3 = np.delete(np_ary2, 0)

#普通の配列に戻す
ary = np_ary3.tolist()
print(ary) #[2, 3, 4, 5, 6, 7, 8, 9, 10]

4. 簡単な計算

配列の全ての要素に対して、値の加算や乗算が行えます。
配列同士で計算する場合は、要素数を合わせる必要があります。

import numpy as np

np_ary  = np.array([1,2,3,4,5])
print(np_ary + 1) #[2 3 4 5 6]
print(np_ary * 3) #[ 3  6  9 12 15]

print(np_ary + [1,1,1,1,1]) #[2 3 4 5 6]

5. 行列の計算

ndarray では2次元配列を行列として見なして、計算を行うことができます。
行列のサイズは shape で取得できます。

$$ \begin{eqnarray}
\begin{pmatrix} 1 & 2 & 3 \cr 4 & 5 & 6 \end{pmatrix}
\begin{pmatrix} 1 \cr 2 \cr 3 \end{pmatrix}
&=& \begin{pmatrix} 1*1+2*2+3*3 \cr 4*1+5*2+6*3 \end{pmatrix} \\
&=& \begin{pmatrix} 14 \cr 32 \end{pmatrix}
\end{eqnarray}
$$

import numpy as np

# 行 * 列 = 2 * 3
a = np.array([
    [1,2,3],
    [4,5,6],
])
print(a.shape) #(2, 3)

# 行 * 列 = 3 * 1
b = np.array([
    [1],
    [2],
    [3]
])
print(b.shape) #(3, 1)

c = a.dot(b)
print(c)
# [[14]
#  [32]]

print(c.shape) #(2, 1)

6. 実数でループ

numpy.arange() で実数の配列を作成して、実数でループさせることができます。
numpy を使わずに、range() の値を 10 などで割って実数にすることもできます。

ループ変数の型は、前者は numpy.float64、後者は float と言う違いがあります。
import numpy as np

for i in np.arange(0, 1, 0.1):
    print(i)   #0.0, 0.1, 0.2 ~ 0.9

for i in range(0, 10):
    idx = i / 10
    print(idx) #0.0, 0.1, 0.2 ~ 0.9

7. 要素のサイズ

ndarray生成時に、要素のサイズを指定できます。
例えば、int8 にすると、要素のサイズは8ビットとなり、値は-128~127の範囲となります。
127 に 1 を加算すると、128 ではなく、-128 になります。
要素のサイズは dtype で設定・取得ができます。

import numpy as np

ary = np.array([1,2,3,4,5,6,7,8,9,10], np.int8)

print(ary.dtype) #int8
ary += 125
print(ary.dtype) #int8

print(ary) #[ 126  127 -128 -127 -126 -125 -124 -123 -122 -121]

また、計算内容・計算方法によって、dtype が変わる可能性があるため要注意です。
import numpy as np

# 加算している値が int8 のため、int8 で計算される
ary = np.array([1,2,3,4,5,6,7,8,9,10], np.int8)
ary2 = ary + 127
print(ary2.dtype) #int8
print(ary2) #[-128 -127 -126 -125 -124 -123 -122 -121 -120 -119]

# 加算している値が int16 のため、int16 で計算される
ary3 = ary + 128
print(ary3.dtype) #int16
print(ary3) #[129 130 131 132 133 134 135 136 137 138]

# += を使うと、dtype が変わらない
ary += 200
print(ary.dtype) #int8
print(ary) #[-55 -54 -53 -52 -51 -50 -49 -48 -47 -46]

8. ビューとコピー

ndarray には、元の ndarray が保持する配列と同じメモリを参照するビューと、異なるメモリを使用するコピーがあります。
計算方法やメソッドによって、戻り値がビューなのか、コピーなのかが決まります。

例えば、配列の一部分をスライスで取得した場合、コピーではなく、ビューとなります。
そのため、取得した一部分の値を変更すると、元の配列の値も変わるため要注意です。

import numpy as np

ary1 = np.array([1,2,3,4,5,6,7,8,9,10])

#一部分を切り取り
ary2 = ary1[0:3]
print(ary2) #[1 2 3]

#切り取った値を変更
ary2[0] = 999

#元の配列にも影響が出る
print(ary1) #[999   2   3   4   5   6   7   8   9  10]
print(ary2) #[999   2   3]

ビュー
import numpy as np

ary1 = np.array([1,2,3,4,5,6,7,8,9,10])
ary2 = ary1

np.add(ary1, 1, out=ary1) #ary1 += ary1 と同じ

ary1[0] = 999

print(ary1) #[999   3   4   5   6   7   8   9  10  11]
print(ary2) #[999   3   4   5   6   7   8   9  10  11]

コピー
import numpy as np

ary1 = np.array([1,2,3,4,5,6,7,8,9,10])
ary2 = ary1

ary1 = np.add(ary1, 1) #ary1 = ary1 + 1 と同じ

ary1[0] = 999

print(ary1) #[999   3   4   5   6   7   8   9  10  11]
print(ary2) #[ 1  2  3  4  5  6  7  8  9 10]


9. 条件に一致する要素への一括代入

指定した条件に一致する要素にのみ代入することができます。
これにより、最小値を下回ったり、最大値を上回る値を、範囲に収めることができます。 二値化なども簡単に行えます。
import numpy as np

np_ary = np.array(range(-5, 10))
print(np_ary) #[-5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8  9]

np_ary[np_ary < 0] = 0
np_ary[np_ary > 5] = 5
print(np_ary) #[0 0 0 0 0 0 1 2 3 4 5 5 5 5 5]