NumPyの使い方(ndarray編)
NumPyのndarrayの使い方のメモです。
NumPy
NumPyは数学関数ライブラリです。
インストール方法は下記を参照。
pppurple.hatenablog.com
IPythonで使ってみます。
In [1]: import numpy as np
ndarray
ndarrayはN次元配列のオブジェクトです。
pythonの配列操作は遅いのですが、ndarrayは高速処理できるように最適化されています。
array()関数に配列を渡して生成します。
In [6]: data = [1, 2, 3, 10] In [7]: arr = np.array(data) In [8]: arr Out[8]: array([ 1, 2, 3, 10])
2次元配列を渡すと、2次元のndarrayが生成されます。
In [9]: data2 = [[1, 2, 3], [4, 5, 6]] In [10]: arr2 = np.array(data2) In [11]: arr2 Out[11]: array([[1, 2, 3], [4, 5, 6]])
次元数、行数、列数
In [12]: arr2.ndim Out[12]: 2 In [13]: arr2.shape Out[13]: (2, 3)
零行列の生成
In [15]: np.zeros(10) Out[15]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) In [16]: np.zeros((5, 5)) Out[16]: array([[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]]) In [18]: np.zeros((2, 5, 5)) Out[18]: array([[[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]], [[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]]])
empty()の場合、要素は不定になります。
In [19]: np.empty(10) Out[19]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) In [21]: np.empty((5, 5)) Out[21]: array([[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]]) In [22]: np.empty((2, 5, 5)) Out[22]: array([[[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]], [[ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]]])
arange()で生成。range()と同様の使い方。
In [24]: np.arange(10) Out[24]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [26]: np.arange(5, 15) Out[26]: array([ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]) In [27]: np.arange(0, 10, 2) Out[27]: array([0, 2, 4, 6, 8])
dtypeでデータ型を表示。int64に推測される。
In [34]: arr Out[34]: array([ 1, 2, 3, 10]) In [35]: arr.dtype Out[35]: dtype('int64')
小数点だとfloatに推測される
In [28]: data3 = [0.1, 0.2, 3, 10] In [31]: arr3 = np.array(data3) In [32]: arr3 Out[32]: array([ 0.1, 0.2, 3. , 10. ]) In [33]: arr3.dtype Out[33]: dtype('float64')
astype()でデータ型をキャスト
int⇒float
In [36]: float_arr = arr.astype(np.float64) In [37]: float_arr Out[37]: array([ 1., 2., 3., 10.]) In [38]: float_arr.dtype Out[38]: dtype('float64')
float⇒int
In [40]: arr2 = np.array([1.1, 2,2, -3.3, 10.1]) In [41]: arr2 Out[41]: array([ 1.1, 2. , 2. , -3.3, 10.1]) In [42]: arr2.astype(np.int32) Out[42]: array([ 1, 2, 2, -3, 10], dtype=int32)
str⇒float
In [45]: str = np.array(['1.1', '2.2', '-3.3', '10.1'], dtype=np.string_) In [46]: str Out[46]: array([b'1.1', b'2.2', b'-3.3', b'10.1'], dtype='|S4') In [49]: str.astype(np.float64) Out[49]: array([ 1.1, 2.2, -3.3, 10.1]) In [50]: str.astype(float) Out[50]: array([ 1.1, 2.2, -3.3, 10.1])
スカラー演算
四則演算では各要素同士が演算される。
In [51]: arr = np.array([[1, 2, 3], [4, 5, 6]]) In [52]: arr Out[52]: array([[1, 2, 3], [4, 5, 6]]) In [53]: arr * arr Out[53]: array([[ 1, 4, 9], [16, 25, 36]]) In [54]: arr - arr Out[54]: array([[0, 0, 0], [0, 0, 0]]) In [55]: 1 / arr Out[55]: array([[ 1. , 0.5 , 0.33333333], [ 0.25 , 0.2 , 0.16666667]]) In [56]: arr ** 2 Out[56]: array([[ 1, 4, 9], [16, 25, 36]])
ndarrayの要素の操作
ndarrayの要素の操作は、pythonの配列操作とほとんど同じ。
要素の参照
In [57]: arr = np.arange(10) In [58]: arr Out[58]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [59]: arr[0] Out[59]: 0 In [60]: arr[5] Out[60]: 5 In [61]: arr[4:9] Out[61]: array([4, 5, 6, 7, 8])
要素の変更
In [62]: arr[4:9] = 100 In [63]: arr Out[63]: array([ 0, 1, 2, 3, 100, 100, 100, 100, 100, 9])
配列スライス
In [64]: arr = np.arange(10) In [65]: arr_slice = arr[4:9] In [66]: arr Out[66]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [67]: arr_slice Out[67]: array([4, 5, 6, 7, 8])
スライスされた要素はコピーではなく、もとのndarrayを参照している。
In [68]: arr_slice[0] = 1000 In [69]: arr_slice Out[69]: array([1000, 5, 6, 7, 8]) In [70]: arr Out[70]: array([ 0, 1, 2, 3, 1000, 5, 6, 7, 8, 9]) In [71]: arr_slice[:] = 9999 In [72]: arr_slice Out[72]: array([9999, 9999, 9999, 9999, 9999]) In [73]: arr Out[73]: array([ 0, 1, 2, 3, 9999, 9999, 9999, 9999, 9999, 9])
多次元配列の要素の参照
In [74]: arr2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) In [75]: arr2 Out[75]: array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) In [76]: arr2[0] Out[76]: array([1, 2, 3]) In [77]: arr2[1] Out[77]: array([4, 5, 6]) In [78]: arr2[2][2] Out[78]: 9 In [79]: arr2[2, 2] Out[79]: 9 In [80]: arr3 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) In [81]: arr3 Out[81]: array([[[ 1, 2, 3], [ 4, 5, 6]], [[ 7, 8, 9], [10, 11, 12]]]) In [88]: arr3[0, 0] Out[88]: array([1, 2, 3]) In [89]: arr3[0, 1] Out[89]: array([4, 5, 6]) In [90]: arr3[0, 1, 0] Out[90]: 4 In [91]: arr3[0, 1, 2] Out[91]: 6
多次元配列の要素の更新
In [80]: arr3 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) In [81]: arr3 Out[81]: array([[[ 1, 2, 3], [ 4, 5, 6]], [[ 7, 8, 9], [10, 11, 12]]]) In [82]: arr3[0] Out[82]: array([[1, 2, 3], [4, 5, 6]]) In [84]: arr3[0] = 100 In [85]: arr3 Out[85]: array([[[100, 100, 100], [100, 100, 100]], [[ 7, 8, 9], [ 10, 11, 12]]])
多次元配列のスライス
In [92]: arr Out[92]: array([ 0, 1, 2, 3, 9999, 9999, 9999, 9999, 9999, 9]) In [93]: arr[1:4] Out[93]: array([1, 2, 3]) In [95]: arr[4:9] Out[95]: array([9999, 9999, 9999, 9999, 9999]) In [96]: arr2 Out[96]: array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) In [97]: arr2[:2] Out[97]: array([[1, 2, 3], [4, 5, 6]]) In [98]: arr2[1:] Out[98]: array([[4, 5, 6], [7, 8, 9]]) In [99]: arr2[:2, 1:] Out[99]: array([[2, 3], [5, 6]]) In [100]: arr2[:] Out[100]: array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) In [101]: arr2[:, :1] Out[101]: array([[1], [4], [7]])
ブールインデックス参照
配列のインデックスにbool値の配列を与え、配列を参照することが出来る。
In [102]: chars = np.array(['A', 'B', 'C', 'D', 'E', 'F', 'G']) In [103]: chars Out[103]: array(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='<U1') In [104]: data = np.random.randn(7, 4) In [105]: data Out[105]: array([[ 0.70412496, -1.22371325, 1.1306193 , -0.9790867 ], [ 0.05970562, 0.02306688, 0.24999045, -0.6384993 ], [-1.64262671, -0.27073472, 1.72457652, 0.57444572], [ 0.17607953, -0.40248292, 0.01224238, -0.62754326], [-1.63882673, -0.90119505, 0.48003654, -0.7851732 ], [ 1.41863212, -0.35522151, 0.34824733, 1.2513504 ], [-1.71087056, 1.15355688, 0.64256637, 0.20287022]])
下記のbool値の配列(3番目だけtrue)が得られる場合、
dataのインデックスに与えることで、3番目の要素を参照できる。
In [106]: chars == 'C' Out[106]: array([False, False, True, False, False, False, False], dtype=bool) In [107]: data[chars == 'C'] Out[107]: array([[-1.64262671, -0.27073472, 1.72457652, 0.57444572]]) In [108]: data[chars == 'C', 2:] Out[108]: array([[ 1.72457652, 0.57444572]])
下記のbool値の配列(3番目以外true)が得られる場合、
dataのインデックスに与えることで、3番目以外の要素を参照できる。
In [109]: chars != 'C' Out[109]: array([ True, True, False, True, True, True, True], dtype=bool) In [110]: data[chars != 'C'] Out[110]: array([[ 0.70412496, -1.22371325, 1.1306193 , -0.9790867 ], [ 0.05970562, 0.02306688, 0.24999045, -0.6384993 ], [ 0.17607953, -0.40248292, 0.01224238, -0.62754326], [-1.63882673, -0.90119505, 0.48003654, -0.7851732 ], [ 1.41863212, -0.35522151, 0.34824733, 1.2513504 ], [-1.71087056, 1.15355688, 0.64256637, 0.20287022]]) In [111]: data[~(chars == 'C')] (data[-(chars == 'C')]はdeprecated) Out[111]: array([[ 0.70412496, -1.22371325, 1.1306193 , -0.9790867 ], [ 0.05970562, 0.02306688, 0.24999045, -0.6384993 ], [ 0.17607953, -0.40248292, 0.01224238, -0.62754326], [-1.63882673, -0.90119505, 0.48003654, -0.7851732 ], [ 1.41863212, -0.35522151, 0.34824733, 1.2513504 ], [-1.71087056, 1.15355688, 0.64256637, 0.20287022]])
bool値の配列であればよいので、下記の様に条件の結合も可能
In [113]: mask = (chars == 'C') | (chars == 'F') In [114]: mask Out[114]: array([False, False, True, False, False, True, False], dtype=bool) In [115]: data[mask] Out[115]: array([[-1.64262671, -0.27073472, 1.72457652, 0.57444572], [ 1.41863212, -0.35522151, 0.34824733, 1.2513504 ]])
bool値の配列であればよいので、下記の様な式でも参照可能
In [116]: data[data < 0] = 0 In [117]: data Out[117]: array([[ 0.70412496, 0. , 1.1306193 , 0. ], [ 0.05970562, 0.02306688, 0.24999045, 0. ], [ 0. , 0. , 1.72457652, 0.57444572], [ 0.17607953, 0. , 0.01224238, 0. ], [ 0. , 0. , 0.48003654, 0. ], [ 1.41863212, 0. , 0.34824733, 1.2513504 ], [ 0. , 1.15355688, 0.64256637, 0.20287022]])
代入も可能
In [122]: data[chars == 'D'] = 9 In [123]: data Out[123]: array([[ 0.70412496, 0. , 1.1306193 , 0. ], [ 0.05970562, 0.02306688, 0.24999045, 0. ], [ 0. , 0. , 1.72457652, 0.57444572], [ 9. , 9. , 9. , 9. ], [ 0. , 0. , 0.48003654, 0. ], [ 1.41863212, 0. , 0.34824733, 1.2513504 ], [ 0. , 1.15355688, 0.64256637, 0.20287022]])
ファンシーインデックス参照
配列のインデックスに整数の配列を与え、配列を参照する。
In [124]: arr = np.empty((8, 4)) In [125]: for i in range(8): .....: arr[i] = i .....: In [126]: arr Out[126]: array([[ 0., 0., 0., 0.], [ 1., 1., 1., 1.], [ 2., 2., 2., 2.], [ 3., 3., 3., 3.], [ 4., 4., 4., 4.], [ 5., 5., 5., 5.], [ 6., 6., 6., 6.], [ 7., 7., 7., 7.]])
整数の配列を渡すと、そのインデックスで取得できる。
In [127]: arr[[7, 6, 0, 2]] Out[127]: array([[ 7., 7., 7., 7.], [ 6., 6., 6., 6.], [ 0., 0., 0., 0.], [ 2., 2., 2., 2.]]) In [128]: arr[-1] Out[128]: array([ 7., 7., 7., 7.]) In [129]: arr[[-1, -3]] Out[129]: array([[ 7., 7., 7., 7.], [ 5., 5., 5., 5.]])
2つのインデックス配列を渡すと、1つ目の配列で1次元を参照し、
2つ目の配列で2次元を参照する。
In [131]: arr2 = np.arange(32).reshape((8,4)) In [132]: arr2 Out[132]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23], [24, 25, 26, 27], [28, 29, 30, 31]]) In [134]: arr2[[1, 2, 3, 4], [0, 2, 3, 1]] Out[134]: array([ 4, 10, 15, 17])
行列の転置
転置行列
In [137]: arr = np.arange(12).reshape(3, 4) In [138]: arr Out[138]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) In [139]: arr.T Out[139]: array([[ 0, 4, 8], [ 1, 5, 9], [ 2, 6, 10], [ 3, 7, 11]])
行列の内積
In [140]: np.dot(arr.T, arr) Out[140]: array([[ 80, 92, 104, 116], [ 92, 107, 122, 137], [104, 122, 140, 158], [116, 137, 158, 179]])
行列の入れ替え
transopse()に入れ替える次元を与え、その順序に入れ替える。
In [141]: arr = np.arange(16).reshape((2, 2, 4)) In [142]: arr Out[142]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]]) In [143]: arr.transpose((1, 0, 2)) Out[143]: array([[[ 0, 1, 2, 3], [ 8, 9, 10, 11]], [[ 4, 5, 6, 7], [12, 13, 14, 15]]]) In [8]: arr.transpose((2, 1, 0)) Out[8]: array([[[ 0, 8], [ 4, 12]], [[ 1, 9], [ 5, 13]], [[ 2, 10], [ 6, 14]], [[ 3, 11], [ 7, 15]]])
swapaxes()で次元を入れ替える。
1次元と2次元を入れ替える例は、transpose((0,2,1))と同じ。
In [144]: arr Out[144]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]]) In [145]: arr.swapaxes(1, 2) Out[145]: array([[[ 0, 4], [ 1, 5], [ 2, 6], [ 3, 7]], [[ 8, 12], [ 9, 13], [10, 14], [11, 15]]]) In [23]: arr.transpose((0, 2, 1)) Out[23]: array([[[ 0, 4], [ 1, 5], [ 2, 6], [ 3, 7]], [[ 8, 12], [ 9, 13], [10, 14], [11, 15]]])
終わり。