Pythonデータ科学常用パッケージ(一)Numpy

11992 ワード

NumPyって何?
今日から続々とデータ科学常用パッケージの基本的な使い方をお届けします
データ分析の仕事は大量の数値演算に関連しており、効率的で便利な科学計算ツールは欠かせない.Python言語は最初は科学計算用に設計された言語ではなく、Pythonの使いやすさを発見する人が増えるにつれて、Pythonに関する多くの外部拡張が現れ、Numpy(Numeric Python)はその一つである.
Numpyは大量の数値プログラミングツールを提供し、ベクトル、マトリクスなどの演算を容易に処理することができ、科学計算の面での人々の仕事を極めて便利にした.一方、Pythonは無料で、高額な費用をかけてMatlabを使うよりも、Numpyの登場でPythonが多くの人に愛されています.
NumPyの使用方法を簡単に見ることができます.
import numpy as np
numpy.version.full_version
'1.16.4'



二、NumPyオブジェクト:配列
NumPyの基本オブジェクトは同じタイプの多次元配列(homogeneous multidimensional array)であり、これはC++の配列と一致し、例えば文字型と数値型は同じ配列に共存できない.先に例を示します.
a = np.arange(20)
print(a)
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]


ここでは,0からステップ長が1,長さが20の1次元配列aを生成した.Pythonのカウントは0から始まり、RとMatlabの利用者は注意が必要です.
「type」関数でaのタイプを表示できます.ここではaがarrayであることを示します.
type(a)
numpy.ndarray



関数「reshape」では、この配列を再構築できます.たとえば、「reshape」のパラメータは各次元のサイズを表し、各次元の順序で配列されています(2次元の場合は行で配列され、Rの列とは異なります).
a = a.reshape(4, 5)
print(a)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]


より高い次元を構築しても問題ありません.
a = a.reshape(2, 2, 5)
print(a)
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]]


aがarrayである以上、arrayの関数を呼び出してaの関連属性をさらに表示することもできます.「ndim」は次元を表示します.「shape」は各次元のサイズを表示します.「size」は、すべての要素の個数を表示し、各次元サイズの積に等しい.「dtype」は要素タイプを表示します.「dsize」は、要素占有(bytes)サイズを表示します.
a.ndim
3



a.shape
(2, 2, 5)



a.size
20



a.dtype
dtype('int32')



三、配列の作成
配列の作成は、変換リストによって実現され、高次元配列は、変換ネストリストによって実現されます.
raw = [0,1,2,3,4]
a = np.array(raw)
a
array([0, 1, 2, 3, 4])



raw = [[0,1,2,3,4], [5,6,7,8,9]]
b = np.array(raw)
b
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])



いくつかの特殊な配列には、4*5の全ゼロマトリクスなど、特別にカスタマイズされたコマンドが生成されます.
d = (4, 5)
np.zeros(d)
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])



デフォルトで生成されるタイプは浮動小数点型で、指定したタイプから整数型に変更できます.
d = (4, 5)
np.ones(d, dtype=int)
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1]])



[0,1]区間の乱数配列:
np.random.rand(5)
array([0.80378557, 0.09833667, 0.95280995, 0.17707594, 0.80651926])



正規分布に従うランダム配列:
np.random.randn(5)
array([ 0.678737  , -1.14965615, -1.40492579,  1.22479651,  0.2751816 ])



四、配列操作
単純な4つの演算は再ロードされ、すべての'+','-','*','/'演算はすべての配列要素に基づいており、加算を例に挙げます.
a = np.array([[1.0, 2], [2, 4]])
print ("a:
",a) b = np.array([[3.2, 1.5], [2.5, 4]]) print ("b:
",b) print ("a+b:
",a+b)
a:
 [[1. 2.]
 [2. 4.]]
b:
 [[3.2 1.5]
 [2.5 4. ]]
a+b:
 [[4.2 3.5]
 [4.5 8. ]]


ここで,aには要素と浮動小数点数が1つしかないが,残りはいずれも整数であり,処理中にPythonは整数を浮動小数点数(配列が同質であるため)に自動的に変換し,2つの2次元配列の加算には各次元の大きさが同じであることが分かった.もちろん、NumPyではこれらの演算子もスカラーと配列を操作することができます.結果として、配列のすべての要素がこのスカラーに対応して演算されます.それとも配列ですか.
print ("3 * a 
",3*a) print ("b + 1.8
",b )
3 * a :
 [[ 3.  6.]
 [ 6. 12.]]
b + 1.8 
 [[3.2 1.5]
 [2.5 4. ]]


C++、'+='、'-='、'*='、'/='オペレータと同様に、NumPyでもサポートされています.
a /= 2
a
array([[0.5, 1. ],
       [1. , 2. ]])



指数を求めるのも簡単です.
print(a)
[[0.5 1. ]
 [1.  2. ]]


print ("np.exp:
",np.exp(a))
np.exp:
 [[1.64872127 2.71828183]
 [2.71828183 7.3890561 ]]


print ("np.sqrt:
",np.sqrt(a))
np.sqrt:
 [[0.70710678 1.        ]
 [1.         1.41421356]]


print ("np.square:
",np.square(a))
np.square:
 [[0.25 1.  ]
 [1.   4.  ]]


print ("np.power:
",np.power(a,3))
np.power:
 [[0.125 1.   ]
 [1.    8.   ]]


2 D配列の最大最小値を知るにはどうすればいいですか?すべての要素の和を計算したいのですが、行によって和を求め、列によって和を求めたいのですが、どうすればいいですか?NumPyのndarrayクラスはすでに関数を作成しました:
a = np.arange(20).reshape(4,5)
a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])



print("sum of all elements in a: " + str(a.sum()))
print("maximum element in a: " + str(a.max()))
print("minimum element in a: " + str(a.min()))
print("maximum element in each row of a: " + str(a.max(axis=1)))
print("minimum element in each column of a: " + str(a.min(axis=0)))
sum of all elements in a: 190
maximum element in a: 19
minimum element in a: 0
maximum element in each row of a: [ 4  9 14 19]
minimum element in each column of a: [0 1 2 3 4]


科学計算では行列演算に多く用いられ,配列を除いてNumPyは行列オブジェクト(matrix)を同時に提供する.マトリクスオブジェクトと配列には主に2つの違いがあります.1つは、マトリクスが2次元であり、配列が任意の正の整数次元であってもよいことです.2つ目は、行列の'*'オペレータが行列乗算を行い、乗算記号の左側の行列列と乗算記号の右側の行列行が等しくなりますが、配列内の'*'オペレータは各要素の対応する乗算を行い、乗算記号の両側の配列は1次元ごとに一致する必要があります.配列はasmatrixまたはmatでマトリクスに変換したり、直接生成したりすることができます.
a = np.arange(20).reshape(4, 5)
a = np.asmatrix(a)
print(type(a))

b = np.matrix('1.0 2.0; 3.0 4.0')
print(type(b))




マトリクスの乗算をもう一度見てみましょう.これはarangeを使用して別のマトリクスbを生成します.arange関数はarange(開始、終了、ステップ長)の方法で等差数列の生成を呼び出すこともできます.ヘッダが尾を含まないことに注意してください.
b = np.arange(2, 45, 3).reshape(5, 3)
b = np.mat(b)
print(b)
[[ 2  5  8]
 [11 14 17]
 [20 23 26]
 [29 32 35]
 [38 41 44]]


私たちの問題に戻って、行列aとbは行列乗算をします.
print ("matrix a:
",a) print("matrix b:
",b) c = a * b print("matrix c:
",c)
matrix a:
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
matrix b:
 [[ 2  5  8]
 [11 14 17]
 [20 23 26]
 [29 32 35]
 [38 41 44]]
matrix c:
 [[ 290  320  350]
 [ 790  895 1000]
 [1290 1470 1650]
 [1790 2045 2300]]


五、配列要素アクセス
配列および行列要素へのアクセスは、下付き文字で行うことができます.次の例は、2 D配列(または行列)です.
a = np.array([[3.2, 1.5], [2.5, 4]])
print(a[0][1])
print(a[0, 1])
1.5
1.5


配列要素の値は、下付きのアクセスで変更できます.
b = a
a[0][1] = 2.0
print(a)
print(b)
[[3.2 2. ]
 [2.5 4. ]]
[[3.2 2. ]
 [2.5 4. ]]


今問題が来て、明らかに直したのはa 0で、どうしてb 0さえ変わったのですか?このトラップはPythonプログラミングで容易にぶつかる.その理由は、Pythonが本当にaをbにコピーするのではなく、bをa対応データのメモリアドレスに指し示したからだ.本当にaをbにコピーするには、copyを使用します.
a = np.array([[3.2, 1.5], [2.5, 4]])
b = a.copy()
a[0][1] = 2.0
print ("a:",a)
print ("b:",b)
a: [[3.2 2. ]
 [2.5 4. ]]
b: [[3.2 1.5]
 [2.5 4. ]]


aに値を再付与すると、aが他のアドレスに指定され、bは元のアドレスに残ります.
a = np.array([[3.2, 1.5], [2.5, 4]])
b = a
a = np.array([[2, 1], [9, 3]])
print ("a:
",a) print ("b:
",b)
a:
 [[2 1]
 [9 3]]
b:
 [[3.2 1.5]
 [2.5 4. ]]


':'を使用すると、マトリクス内の指定されたカラムなど、1次元のすべてのデータにアクセスできます.
a = np.arange(20).reshape(4, 5)
print ("a:
",a) print ("the 2nd and 4th column of a::
",a[:,[1,3]])
a:
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
the 2nd and 4th column of a::
 [[ 1  3]
 [ 6  8]
 [11 13]
 [16 18]]


少し複雑で、いくつかの条件を満たす要素を取り出してみました.これはデータの処理でよく見られ、通常は単行単列で使用されます.次の例では、第1列が5より大きい要素(10および15)に対応する第3列の要素(12および17)を取り出します.
a[:, 2][a[:, 0] > 5]
array([12, 17])



where関数を使用して、配列内の特定の値の位置を検索します.
loc = numpy.where(a==11)
print(loc)
print(a[loc[0][0], loc[1][0]])
(array([2], dtype=int64), array([1], dtype=int64))
11


六、配列操作
マトリクス(または2次元配列)を例にとると、まずマトリクスの回転を見てみましょう.
a = np.random.rand(2,4)
print ("a:
",a) a = np.transpose(a) print ("a is an array, by using transpose(a):
",a) b = np.random.rand(2,4) b = np.mat(b) print ("b:
",b) print ("b is a matrix, by using b.T:
",b.T)
a:
 [[0.49632956 0.65061015 0.36037379 0.29664563]
 [0.18319505 0.45525932 0.08422801 0.75167911]]
a is an array, by using transpose(a):
 [[0.49632956 0.18319505]
 [0.65061015 0.45525932]
 [0.36037379 0.08422801]
 [0.29664563 0.75167911]]
b:
 [[0.51087064 0.2058778  0.88659661 0.78428426]
 [0.62716285 0.46838085 0.63015861 0.69754748]]
b is a matrix, by using b.T:
 [[0.51087064 0.62716285]
 [0.2058778  0.46838085]
 [0.88659661 0.63015861]
 [0.78428426 0.69754748]]


行列の逆:
import numpy.linalg as nlg
a = np.random.rand(2,2)
print ("a:
",a) ia = nlg.inv(a) print ("inverse of a:
",ia) print ("a * inv(a):
",a * ia)
a:
 [[0.7748124  0.08125528]
 [0.99696367 0.73251292]]
inverse of a:
 [[ 1.50551971 -0.16700242]
 [-2.04904025  1.59245703]]
a * inv(a):
 [[ 1.16649535 -0.01356983]
 [-2.04281868  1.16649535]]


フィーチャー値とフィーチャーベクトルを求める
a = np.random.rand(3,3)
eig_value, eig_vector = nlg.eig(a)

print ("eigen value:
",eig_value) print ("eigen vector:
",eig_vector)
eigen value:
 [ 1.75590394+0.j         -0.25188941+0.08867887j -0.25188941-0.08867887j]
eigen vector:
 [[ 0.33976986+0.j          0.47679494-0.21597791j  0.47679494+0.21597791j]
 [ 0.81509742+0.j          0.24255425+0.21077809j  0.24255425-0.21077809j]
 [ 0.46922557+0.j         -0.78915154+0.j         -0.78915154-0.j        ]]


2つのベクトルを列ごとに結合して行列を作成します.
a = np.array((1,2,3))
b = np.array((2,3,4))
print(np.column_stack((a,b)))
[[1 2]
 [2 3]
 [3 4]]


いくつかのデータをループ処理して結果を得た後、結果をマトリクスに結合することは非常に有用であり、vstackとhstackで完成することができる.
a = np.random.rand(2,2)
b = np.random.rand(2,2)
print ("a:
",a) print ("b:
",b) c = np.hstack([a,b]) d = np.vstack([a,b]) print("horizontal stacking a and b:
",c) print("vertical stacking a and b:
",d)
a:
 [[0.50331973 0.49651025]
 [0.89325327 0.31245265]]
b:
 [[0.35846554 0.56841584]
 [0.88041789 0.81287829]]
horizontal stacking a and b:
 [[0.50331973 0.49651025 0.35846554 0.56841584]
 [0.89325327 0.31245265 0.88041789 0.81287829]]
vertical stacking a and b:
 [[0.50331973 0.49651025]
 [0.89325327 0.31245265]
 [0.35846554 0.56841584]
 [0.88041789 0.81287829]]


七、欠落値
欠落値は解析においても情報の一種であり,NumPyは欠落値の記録としてnanを提供しisnanで判定する.
a = np.random.rand(2,2)
a[0, 1] = np.nan
print(np.isnan(a))
[[False  True]
 [False False]]


nan_to_numはnanを0に置き換え、pandasでnan置換値を指定できる関数を提供するために使用できます.
print(np.nan_to_num(a))
[[0.04279427 0.        ]
 [0.08386045 0.3567586 ]]


参考文献
  • http://wiki.scipy.org/Tentati...
  • Sheppard K. Introduction to Python for econometrics, statistics and data analysis. Self-published, University of Oxford, version, 2012, 2.