(番外編)Python Coding Reference — 2.numpy(ndarray) —

2. ndarray

import numpy as np

初期化

1次元リストを、0で初期化

nary = np.zeros(5)
==> array([0., 0., 0., 0., 0.])

1次元リストを、1で初期化(np.ones)

nary = np.ones(5)
==> array([1., 1., 1., 1., 1.])

1次元リストを、同じ任意の値で初期化(np.full)

nary = np.full(5, 999)
==> array([999, 999, 999, 999, 999])
※1つ目の引数が要素数。設定する値が2つ目

空の値で初期化(np.empty)

nary = np.empty(5)
==> array([0., 0., 0., 0., 0.])
※結果はその時々によって異なる。値が不定なので、後続処理で値を指定することが確実な時に使用すること

連番で初期化(np.arange)

nary = np.arange(6)
==> array([0, 1, 2, 3, 4, 5])
※"arrange"(整える)ではなく、"a"(Array)+"range()"なので注意

全て任意の値で初期化(np.array)

nary = np.array([[0,1,2], [4,6,8]])
==> array([[0, 1, 2],
           [4, 6, 8]])

2次元配列はタプルで型指定。次元は行・列の順

nary1 = np.zeros((2,3))
==> array([[0., 0., 0.],
           [0., 0., 0.]])
2次元リストを、任意の値で初期化
nary = np.full((2, 3), 999)
==> array([[999, 999, 999],
           [999, 999, 999]])

0で初期化(np.zeros_like)

既存のndarrayの型に合わせる

nary = np.zeros_like(nary1)
==> array([[0., 0., 0.],
           [0., 0., 0.]])

1で初期化(np.ones_like)

既存のndarrayの型に合わせる

nary = np.ones_like(nary1)
==> array([[1., 1., 1.],
           [1., 1., 1.]])

任意の値で初期化(np.full_like)

既存のndarrayの型に合わせる

nary = np.full_like(nary1, 999)
==> array([[999., 999., 999.],
           [999., 999., 999.]])

空の値で初期化(np.empty_like)

既存のndarrayの型に合わせる

nary = np.empty_like(nary1)
==> array([[0., 0., 0.],
           [0., 0., 0.]])
※empty()と同じく、値が不定なので、後続処理で値を指定することが確実な時に使用すること

CSVファイルから読み込んで初期化(genfromtxt)

読込対象データ(CSV形式で保存しておく)
[sample.csv]
idx,col1,col2,col3
0,1,a,512
1,2,b,128
2,3,c,256
3,4,999,4
全カラム/データ型読込(文字列も読み込むので、dtype付となる)
nary = np.genfromtxt('sample.csv', delimiter=',', encoding='utf-8', names=True, dtype=None)
⇒  array([(0, 1, 'a', 512), (1, 2, 'b', 128), (2, 3, 'c', 256), (3, 4, '999',   4)],
    dtype=[('idx', '<i4'), ('col1', '<i4'), ('col2', '<U3'), ('col3', '<i4')])
ヘッダ行をスキップして2次元で読込む。データ型(dtype)指定しないと文字列はNaNになる
nary = np.genfromtxt('sample.csv', delimiter=',', encoding='utf-8', skip_header=1)
⇒  array([[  0.,   1.,  nan, 512.],
           [  1.,   2.,  nan, 128.],
           [  2.,   3.,  nan, 256.],
           [  3.,   4., 999.,   4.]])
1列目と4列目のカラムのみ読込む。
nary = np.genfromtxt('sample.csv', delimiter=',', encoding='utf-8', usecols=[0,3], names=True, dtype=None)
⇒  array([(0, 512), (1, 128), (2, 256), (3,   4)],
    dtype=[('idx', '<i4'), ('col3', '<i4')])

データ型、情報の取得

初期化
nary = np.ones((2,3))

配列情報

nary.shape
==> (2, 3)
nary.dtype
==> dtype('float64')

データ型の指定

int型を指定する場合
nary = np.ones((2,3), dtype=int)
nary = np.ones((2,3), dtype='int')
==> array([[1, 1, 1],
           [1, 1, 1]])
※intの場合は小数点の表示がない
object型(文字列等)を指定する場合
nary = np.ones((2,3), dtype=object)
==> array([[1, 1, 1],
           [1, 1, 1]], dtype=object)
float型(浮動小数点)を指定する場合
nary = np.ones((2,3), dtype=float)
==> array([[1., 1., 1.],
           [1., 1., 1.]])

データ型の変更(astype)

nary = nary.astype(np.int16)
==> array([[1, 1, 1],
           [1, 1, 1]], dtype=int16)
nary = nary.astype(np.float)
==> array([[1., 1., 1.],
           [1., 1., 1.]])
※floatはデフォルト値なので表示なし。

float型をunicode文字列に変換

nary = nary.astype(np.unicode)
==> array([['1.0', '1.0', '1.0'],
    array([['1.0', '1.0', '1.0'],
※足し算してみると・・・1.01になる
nary[0,0] = nary[0,0] + '1'
array([['1.01', '1.0', '1.0'],
       ['1.0', '1.0', '1.0']], dtype='<U32')

ndarrayの変形(reshape)

2次元を1次元に変換(2×3 -> 6)

nary = np.ones((2,3))
==> array([[1., 1., 1.],
           [1., 1., 1.]])
nary = nary.reshape(6)
==> array([1., 1., 1., 1., 1., 1.])
※要素数が一致していないとエラー
nary = nary.reshape(5)
==> ValueError: cannot reshape array of size 6 into shape (5,)

1次元を2次元に変換(6 -> 3×2)

nary = nary.reshape((3,2))
array([[1., 1.],
       [1., 1.],
       [1., 1.]])

ravel()関数での一次元化(2×3 -> 6)

nary = np.ones((2,3))
nary = np.ravel(nary)
==> array([1., 1., 1., 1., 1., 1.])

ravel()メソッドでの一次元化(2×3 -> 6)

nary = np.ones((2,3))
nary = nary.ravel()
==> array([1., 1., 1., 1., 1., 1.])

flatten()メソッドでの一次元化(2×3 -> 6)

nary = np.ones((2,3))
nary = nary.flatten()
==> array([1., 1., 1., 1., 1., 1.])

要素(単一・行・列)の追加

要素の追加(append)

単一要素の追加

nary = np.ones((2,3))
==> array([[1., 1., 1.],
           [1., 1., 1.]])
np.append(nary, 9)
==> array([1., 1., 1., 1., 1., 1., 9.])
※1次元に変換後に追加される。

行の追加

np.append(nary, np.full(3, 999).reshape(1,3), axis=0)
==> array([[  1.,   1.,   1.],
           [  1.,   1.,   1.],
           [999., 999., 999.]])
※3x2の配列の場合は、reshape(1,3)で1行の配列に変換してからaxis=0でappend

列の追加

np.append(nary, np.full(2, 999).reshape(2,1), axis=1)
==> array([[  1.,   1.,   1., 999.],
           [  1.,   1.,   1., 999.]])
※3x2の配列の場合は、reshape(2,1)で1列の配列に変換してからaxis=1でappend
追加するndarryの型とaxisがマッチしていない場合はエラー
np.append(nary, np.full(2, 999).reshape(2,1), axis=0)
==> ValueError: all the input array dimensions except for the concatenation axis must match exactly

要素の追加(insert)

単一要素の追加

nary = np.ones((2,3))
np.insert(nary, 2, 9)
==> array([1., 1., 9., 1., 1., 1., 1.])
※1次元に変換後に追加される。

行の追加

np.insert(nary, 1, np.full(3, 999).reshape(1,3), axis=0)
==> array([[  1.,   1.,   1.],
           [999., 999., 999.],
           [  1.,   1.,   1.]])
※3x2の配列の場合は、reshape(1,3)で1行の配列に変換してからaxis=0でappend

列の追加

np.insert(nary, 1, 999, axis=1)
==> array([[  1., 999.,   1.,   1.],
           [  1., 999.,   1.,   1.]])
※3x2の配列の場合は、reshape(2,1)で1列の配列に変換してからaxis=1でappend
※ 挿入値はappendと異なり、スカラ値でもリストでもndarrayでも可。以下も同じ結果となる。
np.insert(nary, 1, [999], axis=1)
np.insert(nary, 1, np.full(1, 999), axis=1)
追加するndarryの型とaxisがマッチしていない場合はエラー
np.append(nary, np.full(2, 999).reshape(2,1), axis=0)
==> ValueError: all the input array dimensions except for the concatenation axis must match exactly

2次元ndarrayを指定行に挿入

np.insert(nary, 1, np.full(6, 999).reshape(2,3), axis=0)
==> array([[  1.,   1.,   1.],
           [999., 999., 999.],
           [999., 999., 999.],
           [  1.,   1.,   1.]])
※列数が合っていれば1次元と同様に挿入できる

挿入先を複数指定して挿入

nary = np.ones((2,3))
※先頭行の前と、1行目の後
np.insert(nary, [0,1], np.full(3, 999).reshape(1,3), axis=0)
==> array([[999., 999., 999.],
           [  1.,   1.,   1.],
           [999., 999., 999.],
           [  1.,   1.,   1.]])
 
※1行目の後と2行目の後(この場合は最終行)
np.insert(nary, [1,2], np.full(3, 999).reshape(1,3), axis=0)
==> array([[  1.,   1.,   1.],
           [999., 999., 999.],
           [  1.,   1.,   1.],
           [999., 999., 999.]])

ndarrayの結合(concatenate, hstack, vstack, stack, block)

nary1 = np.ones((2,3))
nary2 = np.full((2,3), 9)

列の追加・結合(hstack)

nary = np.ones((2,3))
np.hstack((nary, np.full(2, 999).reshape(2,1)))
==> array([[  1.,   1.,   1., 999.],
           [  1.,   1.,   1., 999.]])
※引数は1つ。2つの配列はタプルで指定する

行の追加・結合(vstack)

nary = np.ones((2,3))
np.vstack((nary, np.full(3, 999.0).reshape(1,3)))
==> array([[  1.,   1.,   1.],
           [  1.,   1.,   1.],
           [999., 999., 999.]])
※引数は1つ。2つの配列はタプルで指定する

複数のndarrayの結合(concatenate)

デフォルトでは縦方向の結合(axis=0)。結合するndarrayはリストで指定する
np.concatenate([nary1, nary2])
==> array([[1., 1., 1.],
           [1., 1., 1.],
           [9., 9., 9.],
           [9., 9., 9.]])
3つ以上のndarrayの結合も可能
np.concatenate([nary1, nary2, np.zeros((1,3))])
==> array([[1., 1., 1.],
           [1., 1., 1.],
           [9., 9., 9.],
           [9., 9., 9.],
           [0., 0., 0.]])
axisで縦方向の結合も可能
np.concatenate([nary1, nary2], axis=1)
==> array([[1., 1., 1., 9., 9., 9.],
           [1., 1., 1., 9., 9., 9.]])

新しい軸を追加しての結合(stack)

np.stack([nary1, nary2])
==> array([[[1., 1., 1.],
            [1., 1., 1.]],
           [[9., 9., 9.],
            [9., 9., 9.]]])
※2次元配列を2つ重ねた3次元配列となる
※引数となる2つのndarrayはリストで指定する
 
np.stack([nary1, nary2], axis=1)
==> array([[[1., 1., 1.],
            [9., 9., 9.]],
           [[1., 1., 1.],
            [9., 9., 9.]]])
 
※更に軸を変換してのstack
np.stack([nary1, nary2], axis=2)
==> array([[[1., 9.],
            [1., 9.],
            [1., 9.]],
           [[1., 9.],
            [1., 9.],
            [1., 9.]]])

引数の指定方法で結合順が変わる(block)

横方向での結合
np.block([nary1, nary2])
==> array([[1., 1., 1., 9., 9., 9.],
           [1., 1., 1., 9., 9., 9.]])
縦方向への結合
np.block([[nary1], [nary2]])
==> array([[1., 1., 1.],
           [1., 1., 1.],
           [9., 9., 9.],
           [9., 9., 9.]])
このような結合も可能(横に結語してから縦結合。列・行の数が合っていれば)
np.block([[nary1, nary2], [np.zeros(6)]])
==> array([[1., 1., 1., 9., 9., 9.],
           [1., 1., 1., 9., 9., 9.],
           [0., 0., 0., 0., 0., 0.]])

配列の演算

※初期値
nary1 = np.arange(6).reshape(2,3)
nary2 = np.ones((2,3))
nary3 = np.ones((3,2))
nary4 = np.full((2,3) ,2)

加算

nary1 + nary2
==> array([[1., 2., 3.],
           [4., 5., 6.]])

減算

nary1 - nary2
==> array([[-1.,  0.,  1.],
           [ 2.,  3.,  4.]])

乗算

np.dot(nary1, nary3)
==> array([[ 3.,  3.],
           [12., 12.]])

転置(T)

nary1.T
==> array([[0, 3],
           [1, 4],
           [2, 5]])

四則計算

加算(add)

np.add(nary1, nary2)
==> array([[1., 2., 3.],
           [4., 5., 6.]])

減算(subtract)

np.subtract(nary1, nary2)
==> array([[-1.,  0.,  1.],
           [ 2.,  3.,  4.]])

乗算(multiply)

np.multiply(nary1, nary4)
==> array([[ 0,  2,  4],
           [ 6,  8, 10]])

除算(divide)

np.divide(nary1, nary4)
==> array([[0. , 0.5, 1. ],
           [1.5, 2. , 2.5]])

累乗 (power)

np.power(2,3)
==> 8
 
nary1 = np.arange(6).reshape(2,3)
np.power(nary1,3)
==> array([[  0,   1,   8],
           [ 27,  64, 125]], dtype=int32)

平方根 (sqrt)

np.sqrt(9)
==> 3.0
 
np.sqrt(np.array([[4,9,16], [25,36,49]]))
==> array([[2., 3., 4.],
           [5., 6., 7.]])

三角関数 (np.sin、np.cos、np.tan)

※引数となる角度はラジアン単位で指定。ラジアンはnp.radiansで取得可能
例)45度の場合
np.radians(45) = 45 * np.pi / 180
・ 角度=ラジアン=0のとき
np.sin(np.radians(0))
==> 0.0
np.cos(np.radians(0))
==> 1.0
np.tan(np.radians(0))
==> 0.0
・リストで複数を同時に指定することも可能
np.sin(np.radians([0,30,45,90]))
==> array([0.        , 0.5       , 0.70710678, 1.        ])
np.cos(np.radians([0,30,45,90]))
==> array([1.00000000e+00, 8.66025404e-01, 7.07106781e-01, 6.12323400e-17])
np.tan(np.radians([0,30,45,90]))
==> array([0.00000000e+00, 5.77350269e-01, 1.00000000e+00, 1.63312394e+16])
・πが無理数で小数点以下の桁数が大きくなるためnp.roundで四捨五入
np.round(np.sin(np.radians([0,30,45,90])), 3)
==> array([0.   , 0.5  , 0.707, 1.   ])
np.round(np.cos(np.radians([0,30,45,90])), 3)
==> array([1.   , 0.866, 0.707, 0.   ])
np.round(np.tan(np.radians([0,30,45,60])), 3)  # 90は無限大なので
==> array([0.   , 0.577, 1.   , 1.732])

ソート関数(np.sort, np.argsort)

普通のソート

nary = np.array([6,2,0,9,7,4])
==> array([6, 2, 0, 9, 7, 4])
np.sort(nary)
==> array([0, 2, 4, 6, 7, 9])

二次元配列のソート

nary = np.array([[6,0,7],[9,7,3]])
==> array([[6, 0, 7],
           [9, 7, 3]])
 
※デフォルトは行ごとにソート
np.sort(nary)
==> array([[0, 6, 7],
           [3, 7, 9]])

列ごと(縦方向)にソート

np.sort(nary, axis=0)
==> array([[6, 0, 3],
           [9, 7, 7]])
 
※デフォルトはaxis=1
np.sort(nary, axis=1)
==> array([[0, 6, 7],
           [3, 7, 9]])

argsort ソートした際の、元の値のINDEXを返す

nary = np.array([[6,0,7],[9,7,3]])
np.argsort(nary)
==> array([[1, 0, 2],
           [2, 1, 0]], dtype=int32)

欠損値np.nanの扱い

nan値の代入

## 明示的に欠損値NaNを生成したいときはnp.nanやfloat('nan')などを使う
nary = np.ones((2,3))
nary[0,0]=9
nary[1,1]=np.nan
nary[1,2]=float(np.nan)
 
==> array([[ 9.,  1.,  1.],
           [ 1., nan, nan]])

nan値の判定

・np.isnan
True if np.isnan(nary[1,1]) else False
==> True
・"=="では判定不可
True if nary[1,1] == np.nan else False
==> False
・math.isnan
True if math.isnan(nary[1,1]) else False
==> True
・np.nan_to_num()で他の値に置換
True if np.isnan(np.nan_to_num(nary[1,1], 999)) else False
==> False

nanを含むndarrayの集計

nary = array([[  0.,   1.,  nan, 512.],
              [  1.,   2.,  nan, 128.],
              [  2.,   3.,  nan, 256.],
              [  3.,   4., 999.,   4.]])
・nansum()でnanを含むndarrayの合計算出
np.nansum(nary)
==> 1915.0
==> (0+1+2+3+1+2+3+4+999+512+128+256+4) = 1915
・axis=0 で列毎の合計
np.nansum(nary, axis=0)
==> array([  6.,  10., 999., 900.])
==> (1+2+3 = 6, 1+2+3+4 = 10, 999, 512+128+256+4 = 900)
・axis=1 で行毎の合計
np.nansum(nary, axis=1)
==> array([ 513.,  131.,  261., 1010.])
==> (1+512 = 513, 1+2+128 = 131, 2+3+256 = 261, 3+4+999+4 = 1010)

合計と同様に、最大、最小、平均、分散、標準偏差関数が用意されている
np.nanmean(), np.nanmax(), np.nanmin(), np.nanstd(), np.nanvar()

・最大
np.nanmax(nary)
==> 999.9
・最小
np.nanmin(nary)
==> 0.0
・平均
np.nanmean(nary)
==> 147.30769230769232
・分散
np.nanvar(nary)
==> 81540.82840236685
・標準偏差
np.nanstd(nary)
==> 285.553547346845

Posted by tfurukaw