ディープラーニングの実装で、配列や行列の計算を多く使いますが、 NumPy(ナムパイ)の配列クラスに、これらの操作を容易にする機能が提供されています。
>>> import numpy
>>> x=numpy.array([1,2,3]) # [1,2,3]の配列の引数で、NumPyオブジェクトを生成する。
>>> print(x)
[1 2 3]
>>> x
array([1, 2, 3])
>>> x.size # 要素数取得 x.shape[0] や len(x) でも同じ結果が得られる
3
>>> type(x)
<class 'numpy.ndarray'>
>>> x.dtype # z内の内部配列の要素の型を、dtypeで確認しています。
dtype('int32')
>>> y=numpy.array([4,5,6])
>>> x+y # NumPyオブジェクトの加算で、要素毎に加算した新しいNumPyオブジェクトを生成
array([5, 7, 9], dtype=int32)
>>> z=x+y
>>> z
array([5, 7, 9], dtype=int32)
>>> print(z)
[5, 7, 9]
>>> x.tolist() # NumPyから配列を得る
[1, 2, 3]
>>>
次の先頭行のimport numpy as np の記述で「numpyをnpとして読み込み、NumPyに関するメソッドをnpを参照して使えるようにする」記述です。import numpy as np def test(): x=np.array([ 1, 2, 3]) y=np.array([ 4, 5, 6]) print(x+y) # 表示結果:[5 7 9] print(x*y) # 表示結果:[ 4 10 18] print(y-x) # 表示結果:[3 3 3] print(y/x) # 表示結果:[ 4. 2.5 2. ] print(x*2) # 表示結果:[2 4 6] これはブロードキャスト演算と呼ぶ test()NumPyを使うと、一括した比較や抽出、配列の合計も容易に可能です。
>>> x=np.array([ 1, 3, 5]) >>> y=np.array([ 6, 4, 2]) >>> z=np.r_[x, y] # xとyの'numpy.ndarray'を連結 >>> z array([1, 3, 5, 6, 4, 2]) >>> np.argmax(z) #最も大きな要素の添え字を取得 3 >>> z > 2 #一括した比較 array([False, True, True, True, True, False], dtype=bool) >>> z[ z > 2 ] array([3, 5, 6, 4]) >>> >>> np.sum(x) # 配列の合計 9 >>> np.sum(x + y) # 1+6 + 3+4 + 5+2 21 >>> np.sum(x * y) # 1*6 + 3*4 + 5*2 28 >>> >>> z array([1, 3, 5, 6, 4, 2]) >>> w= z < 4 # 比較結果の配列を生成 >>> w array([ True, True, False, False, False, True], dtype=bool) >>> w.astype(np.int) # astypeの引数で指定した型のNumPy配列を生成 (配列要素全体の型変換に使われる。) array([1, 1, 0, 0, 0, 1]) >>>
a=[] a.append([1,2,3]) a.append([4,5]) print(a) # [[1, 2, 3], [4, 5]]ですが、Numpyオブジェクトにはappend命令がありません。
import numpy as np a=np.array([]) # 空で型指定をしないと、'numpy.float64'型になる。 a=np.append(a, [1,2,3]) a=np.append(a, [4,5]) print(a) # [1. 2. 3. 4. 4.] このすべての要素が'numpy.float64'型になる。(リスト要素は、異なる型が記憶できますが、全てがnumpyは同じ型で、「a=np.array([], np.int)」で作ればすべてintです。)
import numpy as np a=np.empty((0,3), int)# 3つ要素の配列を要素とした2次配列 a=np.append(a, [[1, 2, 3]], axis=0) a=np.append(a, [[4, 5, 0]], axis=0) print(a) # [[1 2 3] [4 5 0]] |
import numpy as np a=np.empty((0,3), int)# 3つ要素の配列を要素とした2次配列 a=np.append(a, np.array([[1, 2, 3]]), axis=0) a=np.append(a, np.array([[4, 5, 0]]), axis=0) print(a) # [[1 2 3] [4 5 0]] |
import numpy as np a = np.array([],int) a = np.append(a, [1,2]) a = np.append(a, [3,4]) a = np.append(a, [5,6]) print( a.shape, a) # 出力:(6,) [1 2 3 4 5 6]さて、左下の生成方法は上記と同じ結果で、2次元のNumpyになりません。(右下と同等にはなりません。)
import numpy as np a = np.array([],int) a = np.append(a, np.array([1,2])) a = np.append(a, np.array([3,4])) a = np.append(a, np.array([5,6])) print( a.shape, a) # 出力:(6,) [1 2 3 4 5 6] |
import numpy as np a = np.array([ [1,2],[3,4] ,[5,6] ]) print( a.shape, a) # 出力:(3, 2) [[1 2] [3 4] [5 6]] |
a=np.empty( (0,2) , int) print( a.shape, a) # 出力:(0, 2) [] a = np.append(a, np.array([[1,2]]) ,axis=0) a = np.append(a, np.array([[3,4]]) ,axis=0) a = np.append(a, np.array([[5,6]]) ,axis=0) print( a.shape, a, type(a[0]) # 出力:(3, 2) [[1 2] [3 4] [5 6]] |
a=np.empty( (0,2) , int)
print( a.shape, a) # 出力:(0, 2) []
a = np.append(a, [[1,2]] ,axis=0)
a = np.append(a, [[3,4],[5,6]] ,axis=0)
# 上のように2つ追加することも可能です。
print( a.shape, a, type(a[0]) )
# 出力:(3, 2) [[1 2]
[3 4]
[5 6]]
|
import numpy as np a = np.array([],int) a = np.append(a, [1,2]) a = np.append(a, [3,4]) a = np.append(a, [5,6]) print( a.shape, a) # 出力:(6,) [1 2 3 4 5 6] a=a.reshape(2,3) print( a.shape, a) # 出力:(2, 3) [[1 2 3] [4 5 6]] a=a.reshape(3,2) print( a.shape, a) # 出力:(3, 2) [[1 2] [3 4] [5 6]]
def test(): A=np.array([ 1, 2, 3]) print(A) # 表示結果:[1 2 3] print( "np配列要素型:", A.dtype ) # 表示結果:np配列要素型: int32 print( "np配列の次元数:",np.ndim(A) ) # np配列の次元数: 1 print( "np配列の形状:", np.shape(A) ) # 表示結果:np配列の形状: (3,) print( "np配列の形状:", A.shape ) # 表示結果:np配列の形状: (3,) print( "np配列の形状:", A.shape[0] ) # 表示結果:np配列の形状: 3 len関数を使って「len(A)」も同じ結果です。 test() b=np.array([ 1, 2, 3, 4, , 1.5])
def test(): A=np.array( [ [1,2], [3,4], [5,6] ] ) # 2次配列で、Numpyを生成すると、個々の内部要素もNumpy配列になります。( type(A)もtype(A[0])も'<class 'numpy.ndarray'>') print(A) # 表示結果:[1 2 3] print( "np配列要素型:", A.dtype ) # 表示結果:np配列要素型: int32 print( "np配列の次元数:",np.ndim(A) ) # np配列の次元数: 2 print( "np配列の形状:", np.shape(A) ) # 表示結果:np配列の形状: (3, 2) print( "np配列の形状:", A.shape ) # 表示結果:np配列の形状: (3, 2) print( "np配列の形状:", A.shape[0] ) # 表示結果:np配列の形状: 3 len関数を使っても同じ結果が得られます print( "通常配列変換:", A.tolist() ) # 表示結果:通常配列変換: [[1, 2], [3, 4], [5, 6]] print( "1次np配列へ変換:", A.flatten() ) # 表示結果:1次np配列へ変換: [1 2 3 4 5 6] test()
import numpy as np a = np.arange(12) # 12個の要素の1次元配列を生成。 a # 出力結果: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) a=np.delete(a, [0,1,2]) # 第2引数の添え字が示す要素を削除する(listでなくて 1つのint指定も可)。 # この例と同にように削除が連続要素であれば、range(0,3)でも可能 a # 出力結果: array([ 3, 4, 5, 6, 7, 8, 9, 10, 11]) np.delete(a, range(0,3)) # (aは変更していない)出力結果: array([ 6, 7, 8, 9, 10, 11]) a # 出力結果: array([ 3, 4, 5, 6, 7, 8, 9, 10, 11]) a=np.append(a, [12,13]) # リストを連結 a # 出力結果: array([ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]) a=np.insert(a, 0, [0,1,2]) # 第2引数が0で先頭が挿入位置になる挿入。(listでなくて 1つの挿入したいデータ要素指定も可能)。 a # 出力結果: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]) a=np.delete(a, range(len(a)-2, len(a))) #numpy配列の最後2つを削除する例 a array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) b = np.reshape(a, (3, 4)) # 3×4の2次元配列に変形 b # 出力結果: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7],[ 8, 9, 10, 11]]) c=b.tolist() # npでなく通常の配列(list)へ変換 c # 出力結果: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]] d=b.flatten() # 1次配列へ変換 d # 出力結果: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) e = np.random.choice(100,10) # 乱数を 0から100未満で10個生成 e # 出力結果例: array([86, 46, 95, 99, 25, 97, 17, 53, 83, 60]) f = np.arange(5, 10.1, 0.5) # 5から10までの0.5刻みnumpy配列生成 f # 出力結果例: array([ 5. , 5.5, 6. , 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5, 10. ]) f.tolist() # list「つまり配列」を取得 出力結果例: [5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0]
import numpy as np np.random.seed(123) # 乱数の生成に使う種(シード)を設定 print( np. random .randint( 10, size=5)) # 出力結果:[2 2 6 1 3] print( np. random .randint( 10, size=5)) # 出力結果:[9 6 1 0 1] print( np. random .randint( 10, size=5)) # 出力結果:[9 0 0 9 3] np.random.seed(123) # 乱数の生成に使う種(シード)を設定 print( np. random .randint( 10, size=5)) # 出力結果:[2 2 6 1 3] print( np. random .randint( 10, size=5)) # 出力結果:[9 6 1 0 1] print( np. random .randint( 10, size=5)) # 出力結果:[9 0 0 9 3]種(シード)の値が同じであれば、それから続く乱数の生成パターンで、同じ出力結果が得られるはずです。
a = np.array([1,2]) a # 出力: array([1, 2]) b = np.array([3,4]) b # 出力: array([3, 4]) ab = np.array([ a, b ]) # aとbを要素にするnumpy ab # 出力: array([[1, 2], [3, 4]]) a[0] # 出力: array([1, 2]) ab = np.array([ [1,2], [2,3] ]) # np.array([ a, b ])と同じ内容の配列であることを検証 ab # 出力: array([[1, 2], [3, 4]]) a[0] # 出力: array([1, 2]) ab.ndim # 次元の確認 2 ab.shape # 形の確認 (2, 2) ab[0].ndim # 次元の確認 1 ab[0].shape # 形の確認 (2,) a.ndim # 次元の確認 1 a[0].ndim # なお、0次元配列であるがエラーにはならない。出力: 0 z = np.array([ab,ab,ab,ab]) #3次元配列 z # 出力: array([[[1, 2], [2, 3]], [[1, 2], [2, 3]], [[1, 2], [2, 3]], [[1, 2], [2, 3]]]) z.ndim # 次元の確認 3 z.shape # 形の確認 (4, 2, 2)さて, numpyのsum関数で、合計が次のように得られます。
a = np.array([ [[1,2], [4,5], [6,7]], [[10,20], [40,50], [60,70]] ])
np.sum(a) # 出力: 275 で、全体の合計
では、配列ごとの合計はどのようにすればよいのでしょうか? このような時に引数で軸(axis)を指定します。a = np.array([ [[1,2], [4,5], [6,7]], [[10,20], [40,50], [60,70]] ]) a.shape # 出力: (2, 3, 2) np.sum(a, axis=0) # 出力: array(array([[11, 22], [44, 55], [66, 77]])) 先頭は、1+10、次の値は、2+20 np.sum(a, axis=1) # 出力: array([[ 11, 14], [110, 140]]) 先頭は、1+4+6、次の値は、2+5+7 np.sum(a, axis=2) # 出力: array([[ 3, 9, 13], [ 30, 90, 130]]) 先頭は、1+2、次の値は、4+5もう一つの例を示します。
a = np.array([ [1,2,4,5,6,7], [10,20,40,50,60,70] ]) a.shape # 出力: (2, 6) np.sum(a) # 出力: 275 で、全体の合計 np.sum(a, axis=0) # 出力: array([11, 22, 44, 55, 66, 77]) 先頭は、1+10、次の値は、2+20 np.sum(a, axis=1) # 出力: array([ 25, 250]) 先頭は、1+2+3+4+5+6+7、次の値は、10+20+30+40+50+60+7;0 np.sum(a, axis=2) # 出力: ValueError: 'axis' entry is out of bounds のエラーです2次元なのでNumPyの関数で引数にaxis を指定できるものが次のようにたくさんあります。
import numpy as np a=np.where( [ True, False, False, True] ) print(type(a), a ) # 表示:(array([0, 3], dtype=int64),)
a=np.where( np.array([ 0, 1, 2, 3 ]) % 3 == 0) print(type(a), a ) # 表示:(array([0, 3], dtype=int64),)
a = np.array([1, 2, 5, 4, 3, 6]) np.where( a >= 5) # 条件を満たす要素の取得 表示:(array([2, 5], dtype=int64),) idxs=np.where( a >= 5 )[0] # 条件を満たす要素のインデックスを取得 print(idxs) # [2 5] の表示 if len(idxs) > 0: a2 = a[idxs[0]:] # a >= 5の条件で見つかった所から最後までのリスト取得 print(a2) # [5 4 3 6]条件で要素を指定する。
import numpy as np a=np.array([1,2,5,2,-1,-2,-1,0,3]) print( a ) # 結果:[ 1 2 5 2 -1 -2 -1 0 3] print( a[a>0] ) # 結果:[1 2 5 2 3] a[a<0]=0 # 条件要素の変更 print( a ) # 結果:[1 2 5 2 0 0 0 0 3]
a = np.arange(0, 10.1, 2) a # 出力: array([ 0., 2., 4., 6., 8., 10.]) a[1:4]=9 # a[1] から a[3] までを9に設定 (Pythonのリストではできない操作。) a # 出力: array([ 0., 9., 9., 9., 8., 10.]) a[:4]=2 # 先頭 から a[3] までを2に設定 a # 出力: array([ 2., 2., 2., 2., 8., 10.]) a[4:]=1 # a[4] から 最後までを1に設定 a # 出力: array([ 2., 2., 2., 2., 1., 1.]) a[:]=9 # 全てを9に設定 a # 出力: array([ 9., 9., 9., 9., 9., 9.]) a=np.arange(0,11,2.5) # rangeは整数のみですが、numpyのarangeは浮動小数点も可能 a # 出力:array([ 0. , 2.5, 5. , 7.5, 10. ]) a[1:4] = [9.1, 9.2, 9.3 ] # スライス範囲の置き換え a # array([ 0. , 9.1, 9.2, 9.3, 10. ]) a[1:4] = [9.1, 9.2 ] # スライス範囲の置き換え(置き換え要素数が一致しないエラー) Traceback (most recent call last): File "なお最後の添え字でマイナスを指定すると、後ろの要素からその数の要素を除い配列を表現する。", line 1, in a = np.arange(1,11) a # 出力:array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) b=np.zeros(8,np.float16 )# 0で8個を初期化(ゼロ埋め) b :# array([0., 0., 0., 0., 0., 0., 0., 0.], dtype=float16) a[1:9] = b # bのnumpy配列で、部分的な置き換え(int 要素に float を代入しているが可能) a # 出力:array([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 10])ValueError: cannot copy sequence with size 2 to array axis with dimension 3
>>> a=np.array([1,2,3,4,5,6,7]) >>> a array([1, 2, 3, 4, 5, 6, 7]) >>> a[:-1] array([1, 2, 3, 4, 5, 6]) >>> a[:-2] array([1, 2, 3, 4, 5]) >>> a[::-1] array([7, 6, 5, 4, 3, 2, 1]) >>>
>>> xy= np.array([ [0,1],[2,3],[4,5],[6,7],[8,9] ]) # (5, 2) のshapeで生成
>>> xy
array([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
>>> xy[0:5, 0:2] # 上記xyのすべてを表示させた。
array([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
>>> xy[1:-1,] # 1から「後方より1」の範囲で抽出 なおこの例は「 xy[1:-1,0:2] 」と同じで「0:2」を省略した表記
array([[2, 3],
[4, 5],
[6, 7]])
>>> xy[1:-1, 0:1] # 1から「後方より1」の範囲で抽出
array([[2],
[4],
[6]])
>>> xy[1:-1, 1:] # 1から「後方より1」の範囲で抽出
array([[3],
[5],
[7]])
>>> xy[:, 0] # コンマの後がスライス指定でないので、1次元での抽出になる。
array([0, 2, 4, 6, 8])
>>> xy[:, 1] # コンマの後がスライス指定でないので、1次元での抽出になる。
array([1, 3, 5, 7, 9])
>>>
>>> xy[0:3, 0:2]
array([[0, 1],
[2, 3],
[4, 5]])
>>> xy[0:3, 0:2] = [[91,92],[93,94],[95,96]] # フライス範囲の変更例
>>> xy
array([[91, 92],
[93, 94],
[95, 96],
[ 6, 7],
[ 8, 9]])
>>>
次に表のイメージから、指定列を抽出する例で示す。
t = np.array( [ [1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15], ] ) t # 全てを表示 #array([[ 1, 2, 3, 4, 5], # [ 6, 7, 8, 9, 10], # [ 11, 12, 13, 14, 15]])の表示 t[:, :-2] # 先頭列から、後方より2列までを抽出 #array([[1, 2, 3], # [6, 7, 8], # [11, 12, 13]])の表示 t[:, -2:] # 後方より2列より最後の列までを抽出 #array([[ 4, 5], # [ 9, 10], # [ 14, 15]])の表示 t[:, -2] # 後方より2列だけを一次元で抽出 #array([ 4, 9, 14])の表示 t[:, -1] # 最終列だけを一次元で抽出 #array([ 5, 10, 15])の表示 >>>
a=np.arange(1,3*10+1) a=a.reshape(3,10) print(a) ''' [[ 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]] ''' a = a[:, :4] print(a) ''' [[ 1 2 3 4] [11 12 13 14] [21 22 23 24]] '''
a = np.arange(3*2*4) a = a.reshape(3,2,4) print(a) ''' [[[ 0 1 2 3] [ 4 5 6 7]] [[ 8 9 10 11] [12 13 14 15]] [[16 17 18 19] [20 21 22 23]]] ''' print(a[:,-1]) ''' [[ 4 5 6 7] [12 13 14 15] [20 21 22 23]] '''
a=np.arange(1,9) print( a ) # [1 2 3 4 5 6 7 8] b=np.array([True,False,True,True,False,True,False,False]) print( b ) c=a [ b ] # aの要素で、Trueに対応する要素を取り出す。 print( c ) # [1 3 4 6] print( a % 3 == 0 ) print( a [ a % 3 == 0 ] ) # aの要素で、3の倍数の要素を取り出す # [3 6]
a=np.arange(1,9) print( a ) # [1 2 3 4 5 6 7 8] a2= a[ [ 7,6,0 ] ] # 添え字で、7と6と0の添え字が示す要素を取り出す。 # 上記は、a2=a[ np.array([ 7, 6, 0 ]) ] と、添え字配列にndarrayを使うこともできます。 print(a2) # [8 7 1] a[7], a[6], a[0] が表示
a=np.arange(0,10*4) a=a.reshape(4,10) print(a) ''' [[ 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 32 33 34 35 36 37 38 39]]''' a2=a[:,[ 7, 6, 0 ] ] # 上記は、a2=a[:,np.array([ 7, 6, 0 ]) ] と、添え字配列にndarrayを使うこともできます。 print(a2) ''' [[ 7 6 0] [17 16 10] [27 26 20] [37 36 30]]'''
A=np.array( [ [1,2], [3,4], [5,6] ] ) | |
B=np.array( [ 10, 20, 30 ] ) A * B | Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operands could not be broadcast together with shapes (3,2) (3,) |
B=np.array( [ 10, 20 ] ) | この要素数2が、上記のように合わないとエラーです。 |
A * B | array([[ 10, 40],
[ 30, 80],
[ 50, 120]]) |
for row in A: print(row) | [1 2] [3 4] [5 6] |
for row in A:
for e in row:
print(e, " " , end="")
| 1 2 3 4 5 6 |
for x in range(0, A.shape[0], 1):
for y in range(0, A[x].shape[0], 1):
print( A[x][y], " " , end="")
| 1 2 3 4 5 6 |
>>> A=np.array([ [1, 2], [3, 4] ])
>>> A.shape
(2, 2)
>>> B=np.array([ [5, 6], [7, 8] ])
>>> B.shape
( 2, 2)
>>> np.dot(A,B) #ドット積
array([[19, 22],
[43, 50]])
>>>
2の列数と 2 の行数が一致しなければなりません。>>> A=np.array([ [1, 2, 3], [4, 5, 6] ]) >>> A.shape (2, 3) >>> B=np.array([ [1, 2], [3, 4] ]) >>> B.shape (2, 2) >>> np.dot(A,B) #ドット積 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: shapes (2,3) and (2,2) not aligned: 3 (dim 1) != 2 (dim 0) >>>上記は、2×3の行列と、、2×2の行列の積はできないのでエラーが生じています。
>>> A=np.array([ [1, 2, 3], [4, 5, 6] ])
>>> A.shape
(2, 3)
>>> B=np.array([ [1, 2], [3, 4], [5, 6] ])
>>> B.shape
(3, 2)
>>> np.dot(A,B) #ドット積
array([[22, 28],
[49, 64]])
>>>
>>> A=np.array([ [1, 2], [3, 4], [5, 6] ])
>>> A.shape
(3, 2)
>>> B=np.array([ [1, 2, 3, 4], [5, 6, 7, 8]])
>>> B.shape
(2, 4)
>>> np.dot(A,B) #ドット積
array([[11, 14, 17, 20],
[23, 30, 37, 44],
[35, 46, 57, 68]])
>>>
>>> A=np.array([ [1, 2], [3, 4], [5, 6] ])
>>> A.shape
(3, 2)
>>> B=np.array([ [1], [2] ])
>>> B.shape
(2, 1)
>>> np.dot(A,B) #ドット積
array([[ 5],
[11],
[17]])
>>>
>>> A=np.array([ [1, 2], [3, 4], [5, 6] ]) >>> A.shape (3, 2) >>> B=np.array([ 1, 2 ]) >>> B.shape (2,) >>> np.dot(A,B) #ドット積 array([ 5, 11, 17]) >>>
>>> import numpy as np >>> A=np.array([ 1, 2 ]) >>> A.shape (2,) >>> B=np.array( [ [ 1, 2, 3 ], [4, 5 , 6] ] ) >>> B.shape (2, 3) >>> np.dot(A, B) #ドット積 array([ 9, 12, 15]) >>>
import numpy as np a=np.arange(2*3).reshape(2,3) print(a) ''' [[0 1 2] [3 4 5]] ''' it=np.nditer(a,flags=['multi_index']) while not it.finished: idx = it.multi_index print(idx, a[idx]) it.iternext() ''' (0, 0) 0 True (0, 1) 1 True (0, 2) 2 True (1, 0) 3 True (1, 1) 4 True (1, 2) 5 False '''nditer()の指定ではflags=以外に op_flags=['readwrite']や op_flags=['readonly']があるるようです。 |
import numpy as np a=np.arange(2*3*2).reshape(2,3,2) print(a) ''' [[[ 0 1] [ 2 3] [ 4 5]] [[ 6 7] [ 8 9] [10 11]]] ''' it=np.nditer(a,flags=['multi_index']) while it.iternext(): # ここで、イテレータを進ませてしまう。 idx = it.multi_index print(idx, a[idx]) '''この構造のループでは先頭要素にアクセスできないことに注意 (0, 0, 1) 1 (0, 1, 0) 2 (0, 1, 1) 3 (0, 2, 0) 4 (0, 2, 1) 5 (1, 0, 0) 6 (1, 0, 1) 7 (1, 1, 0) 8 (1, 1, 1) 9 (1, 2, 0) 10 (1, 2, 1) 11 ''' for |
格子点 を生成するnp.meshgrid関数で、2点格子の例です。これを使うと、格子点の計算が容易になります。
x=np.arange(5) y=np.arange(10,40,10) print(x,y) # [0 1 2 3 4] [10 20 30] xx,yy=np.meshgrid(x, y) print(xx) ''' [[0 1 2 3 4] [0 1 2 3 4] [0 1 2 3 4]]''' print(yy) ''' [[10 10 10 10 10] [20 20 20 20 20] [30 30 30 30 30]]''' nn=xx.shape[0] for ix in range(nn): for iy in range(nn): print(xx[ix][iy],yy[ix][iy]) ''' 0 10 1 10 2 10 0 20 1 20 2 20 0 30 1 30 2 30 '''
numpyの要素は、全て同じ型(dtypeで指定)です。そしてnumpy要素で使われる型はPython既存の型と異なり、
次のような種類があります。
| データ型 dtype | 型コード | 説明 | Python既存型 |
|---|---|---|---|
| int8 | i1 | 符号あり8ビット整数型 | x |
| int16 | i2 | 符号あり16ビット整数型 | x |
| int32 | i4 | 符号あり32ビット整数型 | int |
| int64 | i8 | 符号あり64ビット整数型 | x |
| uint8 | u1 | 符号なし8ビット整数型 | x |
| uint16 | u2 | 符号なし16ビット整数型 | x |
| uint32 | u4 | 符号なし32ビット整数型 | x |
| uint64 | u8 | 符号なし64ビット整数型 | uint |
| float16 | f2 | 半精度浮動小数点型(符号部1ビット、指数部5ビット、仮数部10ビット) | x |
| float32 | f4 | 単精度浮動小数点型(符号部1ビット、指数部8ビット、仮数部23ビット) | x |
| float64 | f8 | 倍精度浮動小数点型(符号部1ビット、指数部11ビット、仮数部52ビット) | float |
| float128 | f16 | 四倍精度浮動小数点型(符号部1ビット、指数部15ビット、仮数部112ビット) | x |
| complex64 | c8 | 複素数(実部・虚部がそれぞれfloat32) | x |
| complex128 | c16 | 複素数(実部・虚部がそれぞれfloat64) | x |
| complex256 | c32 | 複素数(実部・虚部がそれぞれfloat128) | x |
| bool | ? | ブール型(True or False) | x |
| unicode | U | Unicode文字列 | str |
| object | O | Pythonオブジェクト型 | x |
例えば、np.array([1,2,3]) で生成すると、各要素は'int64'になります。
この表現は、np.array([1,2,3], np.int64)と同じです。
(np.array([1,2,3], np.int)の表現も使えますが、Python2かPython3か、32ビットか64ビットによって異なるでしょう。)
各要素を -128〜127の1byte整数の要素にする場合は、次のような生成表現になります。
np.array([1,2,3], np.int8) np.array([1,2,3], dtype='int8') np.array([1,2,3], dtype='i1') #(型コードで指定)
上記3通りのどれを使っても同じです。「npオブジェクト」.dtype の表現で型を確認できます。
(各データ型の取り得る値の範囲は、整数int, uintの場合に np.iinfo()、
浮動小数点数の場合は、np.finfo()で確認できる。)
numpy要素の型を一括して、異なる型のnumpyを生成するメソッドが、astype( dtype )です。
a = np.array([1,2,3]) print( a.dtype ) a = np.array([1,2,3], np.int8) print( a.dtype ) a2 = a.astype( np.int ) # 全ての要素をnp.intに変換している。(np.int32と指定した方が明確である) print( a2.dtype ) print( np.iinfo( np.int8 ) ) #iinfo(min=-128, max=127, dtype=int8) print( np.iinfo( np.int ) ) #iinfo(min=-2147483648, max=2147483647, dtype=int32)
この表現を使うとsin波形の生成は、次 ((0x1ff * np.sin(np.arange(-np.pi, np.pi, 0.1))).astype(np.int16)+0x1ff).tobytes()
numpyの基本的な型は、真偽値 (bool),(符号付き)整数 (int),符号なし整数 (uint),浮動小数点数 (float),複素数 (complex)です。 ただし、bool型を除いたデータ型はそれぞれ異なるサイズがあります。 たとえば、int型なら、numpy.int8,numpy.int16,numpy.int32,numpy.int64 です。 以下は、バイナリ情報の並びが16ビットリトルエンディアンの並びとして、数値演算(ここでは、* 1.0)して、再びバイナリに戻す例を示します。 import numpy as np buffer1=b"\x06\x00\x06\x00\x03\x00\x02\x00\x03\x00\x03\x00\xfd\xff\xfc\xff\xfb\xff\xfa\xff\xfc\xff\xfe\xff\x00\x00\xfc\xff\xf8\xff" y1 = np.frombuffer(buffer1, dtype="int16") # bufferのバイナリが、16bit整数(リトルエンディアン)である前提で、1次numpyの配列に変換 y1=y1*1 # 例として *1 の演算 y2=y1.astype(np.int16) # float の要素を、16ビット整数群に変更 buffer2=b''.join(y2) # バイナリに戻す print(buffer1) print(buffer2) # 上記と比較している。 以下で、符号ありバイト列を用意して、その先頭要素が符号ありであれば、符号なしバイトに変換する例を示す。 なお型は「isinstance」関数で判定できる。以前は文字の判別のとき、(str,unicodeなどをorで判定する必要があったが、Python3では「basestring」で判定できる) a=np.array([1,127,-1, -128], np.int8) a #出力:array([ 1, 127, -1, -128], dtype=int8) if isinstance(a[0], np.int8) : #要素の型判定 a = a.astype(np.uint8) a #出力:array([ 1, 127, 255, 128], dtype=uint8)
a=np.array([128, 32767], dtype=np.int16) b=a.tobytes() print(b) # 表示内容:b'\x80\x00\xff\x7f'
a32=np.array([128, 32767]) print( a32.dtype) # 表示内容:int32 print(a32.tobytes()) # 表示内容:b'\x80\x00\x00\x00\xff\x7f\x00\x00' a16=a32.astype(np.int16) print( a16.dtype) # 表示内容:int16 b16=a16.tobytes() print(b16) # 表示内容:b'\x80\x00\xff\x7f'