pythonで多次元配列を扱う
pythonで配列を扱うライブラリとして有名なのはnumpyというものです。
Python はインタプリタ言語であり、数学のアルゴリズムはC言語などのコンパイル言語やJavaなどと比べて低速に動作する場合が多い。NumPy はこうした問題を、多次元配列と、配列を操作する多数の関数や演算子を提供することでこの問題を解こうとしている。これにより、配列や行列の操作として記述できるアルゴリズムは、等価な C のコードとほぼ同等の速度で動作する。
NumPy - Wikipedia
とあるように、非常に高速にかつ簡単に行列計算を行なうことができます。
matplotlibは、numpyの行列を処理してグラフの作成をしています。
また、データ処理にも活躍してくれることでしょう。
というわけで、自分がよく使う関数等をまとめておきます。
配列の生成
numpyは多次元配列を操作するライブラリです。
主として、arrayオブジェクトを操作していくことになります。
matrixというクラスも用意されているようですが、基本的にはarrayを使っていくことになります。
arrayの生成にはいくつか方法があり、自分が良く使うのは、
- リストから変換
- arange, linspace関数
- ファイルからloadtxt (ここに並べて良いかわかんないけど)
えす。他にも手法はあるようです。
リストから変換
Python組み込みのリストからarrayを生成することができます。
>>> from numpy import * >>> array([1,2,3]) array([1, 2, 3]) >>> >>> array([1., 2., 3.]) array([ 1., 2., 3.]) >>> >>> array([1, 2, 3], dtype=float) # dtypeを指定することでarrayの型が決まる array([ 1., 2., 3.])
リストからの生成にはarray()を用います。
データ型はリスト内の型から決定されますが、dtypeを指定することで、arrayの型を決定することできます。
arange(), linspace()
arange()はrange()と似ていますが、rangeがリストを返すのに対しarangeはarrayを返します。
引数が浮動小数でも良いのが特徴でしょうか。
>>> arange(0, 10, 0.1) # 0から10まで0.1刻みで。 array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4. , 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5. , 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6. , 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7. , 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8. , 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9. , 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9])
arange関数はある範囲内を、指定したステップで区切っていきます。
従って、arrayの中の要素がいくつになるかは計算しないと分かりません。
ある範囲を、指定した要素数になるように区切るにはlinspace関数を使います。
>>> linspace(0, 2, 20) # 0から2までの間で20個の要素を作ること >>> a = linspace(0, 2, 20) >>> a array([ 0. , 0.10526316, 0.21052632, 0.31578947, 0.42105263, 0.52631579, 0.63157895, 0.73684211, 0.84210526, 0.94736842, 1.05263158, 1.15789474, 1.26315789, 1.36842105, 1.47368421, 1.57894737, 1.68421053, 1.78947368, 1.89473684, 2. ]) >>> >>> len(a) 20
ファイルから
ファイルからarrayを作成する方法にもいくつかあるようですが、
ここでは、空白区切りのテキストファイルを読み込みます。
0 10 20
1 20 30
2 40 90
3 50 120
4 80 240
それにはloadtxt関数を使います。
>>> from numpy import * >>> data = loadtxt("data.txt") # 上のデータはdata.txtに保存してあります。 >>> data array([[ 0., 10., 20.], [ 1., 20., 30.], [ 2., 40., 90.], [ 3., 50., 120.], [ 4., 80., 240.]]) >>> data[1,:] # 2行目の取得(添字は0から始まるので) array([ 1., 20., 30.]) >>> data[:,1] # 2列目の取得 array([ 10., 20., 40., 50., 80.])
以下はRoutines — NumPy v1.16 Manualからの引用です。
>>> from numpy import * >>> >>> data = loadtxt("myfile.txt") # myfile.txt contains 4 columns of numbers >>> t,z = data[:,0], data[:,3] # data is 2D numpy array >>> >>> t,x,y,z = loadtxt("myfile.txt", unpack=True) # to unpack all columns >>> t,z = loadtxt("myfile.txt", usecols = (0,3), unpack=True) # to select just a few columns >>> data = loadtxt("myfile.txt", skiprows = 7) # to skip 7 rows from top of file >>> data = loadtxt("myfile.txt", comments = '!') # use '!' as comment char instead of '#' >>> data = loadtxt("myfile.txt", delimiter=';') # use ';' as column separator instead of whitespace >>> data = loadtxt("myfile.txt", dtype = int) # file contains integers instead of floats
適当に訳すと(超意訳)
>>> from numpy import * >>> >>> data = loadtxt("myfile.txt") # myfile.txtは4つの列を含みます >>> t,z = data[:,0], data[:,3] # dataは2次元のnumpyのarrayとなっています >>> >>> t,x,y,z = loadtxt("myfile.txt", unpack=True) # 全ての列をまとめずに取り出します >>> t,z = loadtxt("myfile.txt", usecols = (0,3), unpack=True) # 使用する列を指定して取りだします >>> data = loadtxt("myfile.txt", skiprows = 7) # ファイルの7行目は無視して他を取り出します >>> data = loadtxt("myfile.txt", comments = '!') # 通常は#がコメントだが、!をコメントとする(ファイル内の) >>> data = loadtxt("myfile.txt", delimiter=';') # スペースでなく、;をデータの区切りに使用 >>> data = loadtxt("myfile.txt", dtype = int) # 浮動小数でなく、整数のデータを取り出す
といった具合にデータを取り出すことができます。
loadtxtは実験データの処理等に便利ですね。
スライス
スライスは、Pythonのリストと同様にできます。
2次元配列の場合[行, 列]で取り出せます。
:を上手に使うことで、行や列の取り出しも自由です。
>>> a = array([[1,2,3], [4,5,6], [7,8,9]]) >>> a array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> a[1,2] 6 >>> a[0,:] # 1行目の取り出し array([1, 2, 3]) >>> a[1,:] # 2行目の取り出し array([4, 5, 6]) >>> a[:,1] # 2列目の取り出し array([2, 5, 8])
計算
算術演算は、要素ごとに行なわれます。
例えばA+Bの場合、A[0,0]とB[0,0]、A[0,1]とB[0,1]....といった感じです。
かけ算の場合でも同様です。(行列のかけ算にはなりません。)
所謂行列のかけ算をしたい時はdot()関数を使ってください。
また、行列用の数学関数がnumpyではあらかじめ用意されています。
numpy.cosなどは行列の計算を行なうことができます。
>>> from numpy import * >>> a = random.random((3,3)) # numpy.random.random。3*3のarrayを作成 >>> b = array([[1,2,3], [4,5,6], [7,8,9]]) >>> a array([[ 0.70235191, 0.48829014, 0.33720279], [ 0.64187382, 0.63667402, 0.4107362 ], [ 0.79077403, 0.80895472, 0.5039849 ]]) >>> b array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> a + b array([[ 1.70235191, 2.48829014, 3.33720279], [ 4.64187382, 5.63667402, 6.4107362 ], [ 7.79077403, 8.80895472, 9.5039849 ]]) >>> a * b # 行列のかけ算ではない array([[ 0.70235191, 0.97658027, 1.01160836], [ 2.56749528, 3.18337011, 2.46441719], [ 5.53541819, 6.47163772, 4.53586408]]) >>> cos(a) array([[ 0.76332493, 0.88313627, 0.94368381], [ 0.80097531, 0.80407758, 0.91682712], [ 0.70329527, 0.69025514, 0.87566514]]) >>> exp(a*1j) array([[ 0.76332493+0.64601475j, 0.88313627+0.46911653j, 0.94368381+0.33084871j], [ 0.80097531+0.59869737j, 0.80407758+0.59452439j, 0.91682712+0.3992844j ], [ 0.70329527+0.71089786j, 0.69025514+0.72356606j, 0.87566514+0.4829188j ]])
他にも私がよく使うメソッド。
>>> a array([[ 0.70235191, 0.48829014, 0.33720279], [ 0.64187382, 0.63667402, 0.4107362 ], [ 0.79077403, 0.80895472, 0.5039849 ]]) >>> a.sum() # 合計 5.3208425191396165 >>> a.max() # 最大値 0.80895471516033424 >>> a.min() # 最小値 0.33720278811620497
続きはまた今度