NumPyには、数値計算を目的としたライブラリであるため、あらかじめ数学関数が数多く用意されています。NumPyの数学関数を知っていると、自分で実装する手間が省けます。
そこで、この記事を読めば一通りよく使う関数を把握することができるように、NumPyの数学関数を中心に使い方を紹介します。
四則演算
まずは基本的な四則演算を紹介します。四則演算はPythonにある+
,-
,+
,/
の4つの演算子を適用することができます。この場合、配列の各要素に対して演算が行われることになります。
どのshape
同士のndarrayを計算することができるかは、NumPyのブロードキャストで詳しく解説しているので、以下の記事を参考にしてください。
NumPyのブロードキャストのメリットと解説 /features/numpy-broadcasting.html
四則演算に相当するNumPyの関数(np.add()
など)がありますが、ndarrayの配列操作であることを明示したい場合以外にはあまり使用されません。
足し算(np.add)
足し算です。特別な関数とかはなく、演算子の+
を用います。配列の要素同士の足し算ができるだけでなく、配列の各要素に同じ値を加算することも可能です。
In [1]: import numpy as np
In [2]: a = np.array([0, 1, 2, 3, 4])
In [3]: b = np.array([2, 4, 6, 8, 10])
In [4]: a + b # 配列同士を足し合わせると各々の要素の和が返ってくる。
Out[4]: array([ 2, 5, 8, 11, 14])
In [5]: a + 4 # 各要素に4を足す
Out[5]: array([4, 5, 6, 7, 8])
引き算(np.subtract)
引き算も全く同様に-
演算子で処理することが可能です。
In [6]: a - b # 先ほど作ったa,bを用いる。
Out[6]: array([-2, -3, -4, -5, -6])
In [7]: b - a
Out[7]: array([2, 3, 4, 5, 6])
In [8]: a - 4 # 各々の要素から4ずつ引く。
Out[8]: array([-4, -3, -2, -1, 0])
掛け算(np.multiply)
掛け算は、*
演算子を用いて計算します。この場合、配列同士のそれぞれ対応する要素同士の掛け算を行います。外積や内積といったベクトルや行列の演算とは違い、アダマール積と呼ばれる成分同士の演算なので注意してください。
In [9]: a * b
Out[9]: array([ 0, 4, 12, 24, 40])
In [10]: a * 2
Out[10]: array([0, 2, 4, 6, 8])
割り算・剰余(np.divide, np.mod)
割り算は/
演算子を使います。また、商を整数にしたい場合はPython3の演算子と同様に//
とスラッシュを2回続けて使うとできます。剰余を求めたいときは%
を使います。全てPythonと同じ演算子なので直感的に演算することができます。
In [11]: b / a # b÷aを行うが、aの要素の中に0が含まれているので1つだけ無限を表す`inf`になっている。
Out[11]: array([ inf, 4. , 3. , 2.66666667, 2.5 ])
In [12]: b / 2 # 2でわってみる
Out[12]: array([ 1., 2., 3., 4., 5.])
In [13]: b / 3 # 3でわってみる
Out[13]: array([ 0.66666667, 1.33333333, 2. , 2.66666667, 3.33333333])
In [14]: b // 3
Out[14]: array([0, 1, 2, 2, 3])
In [15]: b % 3
Out[15]: array([2, 1, 0, 2, 1])
剰余(%)と同じことはnp.mod()
でもすることができる。
In [15]: np.mod(b, 3) # 3で割ったあまり
Out[15]: array([2, 1, 0, 2, 1])
累乗(np.power)・平方根(np.sqrt)
累乗はnp.power(x, t)
でを求められます。また、Pythonのビルトイン演算子と同様にx**2
で求めることも可能です。平方根を求めたいときはnp.sqrt(x)
で求めることができます。
In [1]: import numpy as np
In [2]: np.power(2, 3) # 2の3乗の値を求める。
Out[2]: 8
In [3]: 2**3 # これはPythonの累乗計算
Out[3]: 8
In [4]: a = np.arange(1, 11, 1)
In [5]: b = np.array([1,2,1,2,1,2,1,2,1,2])
In [6]: a
Out[6]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [7]: b
Out[7]: array([1, 2, 1, 2, 1, 2, 1, 2, 1, 2])
In [8]: np.power(a, b) # 1乗、2乗の値が交互に出る。
Out[8]: array([ 1, 4, 3, 16, 5, 36, 7, 64, 9, 100])
In [9]: a ** b # 同様に
Out[9]: array([ 1, 4, 3, 16, 5, 36, 7, 64, 9, 100])
In [10]: np.sqrt(2) # 平方根はnp.sqrt()を使う
Out[10]: 1.4142135623730951
In [11]: 2 ** 0.5 # もちろんこのようにして平方根を求めることもできる。
Out[11]: 1.4142135623730951
In [12]: np.sqrt(a) # もちろん、配列を入れることも可能。
Out[12]:
array([ 1. , 1.41421356, 1.73205081, 2. , 2.23606798,
2.44948974, 2.64575131, 2.82842712, 3. , 3.16227766])
三角関数
以下では、三角関数の基本であるサイン、コサイン、タンジェントからその逆関数、また度からラジアンへ変換する関数などを紹介します。引数としてndarrayを指定することができます。
三角関数(np.sin, np.cos, np.tan)
NumPyにはサイン、コサイン、タンジェントを計算する関数も実装されています。それぞれ、np.sin()
,np.cos()
,np.tan()
を使います。また、円周率を示すnp.pi
もあります。
引数には、degreeではなくradianを指定します。
In [1]: import numpy as np
In [2]: np.sin(0)
Out[2]: 0.0
In [3]: np.cos(0)
Out[3]: 1.0
In [4]: np.tan(0)
Out[4]: 0.0
In [5]: np.sin(np.pi*0.5) # π/2のときのサインの値は1
Out[5]: 1.0
In [6]: np.cos(np.pi*0.5) # 0になるはず。
Out[6]: 6.123233995736766e-17
In [7]: np.tan(np.pi*0.5) # 無限に発散する。
Out[7]: 16331239353195370.0
In [8]: np.sin(1)
Out[8]: 0.8414709848078965
In [9]: np.cos(1)
Out[9]: 0.54030230586813977
In [10]: np.tan(1)
Out[10]: 1.5574077246549021
逆三角関数(np.arcsin, np.arccos, np.arctan)
三角関数の逆関数もNumPyの関数として存在します。関数名の頭にarc
が付きます。逆関数なので、例えばarcsin
はsin(x)=y
のとき、x
の値を求めたかったらarcsin(y) = x
として求めることができます。
ここでも出力される値はdegreeではなくradianになります。
In [1]: import numpy as np
In [2]: np.arcsin(0.5)
Out[2]: 0.52359877559829882
In [3]: np.arccos(0.5)
Out[3]: 1.0471975511965976
In [4]: np.arctan(1.0)
Out[4]: 0.78539816339744828
In [5]: np.arcsin(-1.0)
Out[5]: -1.5707963267948966
In [6]: np.arccos(-1.0)
Out[6]: 3.1415926535897931
In [7]: np.arctan(-0.5)
Out[7]: -0.46364760900080615
ラジアンと度の相互変換
NumPyで実装されている三角関数系の関数は基本的にradianで操作されます。そのため、度をラジアン、ラジアンを度に変換する関数が必要になります。関数を使わなくても、をかければラジアンに変換することができ、をかければ度に変換することができますが、この操作をする関数が分かりやすいように用意されています。
そこで、NumPyではnp.rad2deg()
がdegreeへの変換として存在し、np.radians()
とnp.deg2rad()
がラジアンへの変換用の関数として存在しています。
In [54]: import numpy as np
In [55]: np.radians(120)
Out[55]: 2.0943951023931953
In [56]: np.deg2rad(120)
Out[56]: 2.0943951023931953
In [57]: np.rad2deg(3.14)
Out[57]: 179.9087476710785
In [58]: np.deg2rad(np.rad2deg(2.3))
Out[58]: 2.3
実行速度も比べてみましょう。
In [8]: %timeit np.radians(24)
1.44 µs ± 89.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [9]: %timeit np.deg2rad(24)
1.43 µs ± 37.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.44マイクロ秒と、1.43マイクロ秒なのでほとんど差はありません。
指数関数、対数関数
指数関数
指数関数のなかでもネイピア数 を底(base)とするものがNumPyでは実装されています。のことです。
これはnp.exp(x)
で計算することが可能です。ネイピア数自体はnp.e
で出すことができます。
In [1]: import numpy as np
In [2]: np.exp(1) # 1乗
Out[2]: 2.7182818284590451
In [3]: np.exp(2)
Out[3]: 7.3890560989306504
In [4]: np.exp(0)
Out[4]: 1.0
ネイピア数に関しての詳しい解説は以下のサイトでされているので参考にしてみてください。
ネイピア数eの定義がなぜあの形か、先生は説明をしてくれなかった
対数関数
対数関数は底が特殊な場合のみ用意されています。
- 底がネイピア数e
np.log(x)
- 底が2
np.log2(x)
- 底が10
np.log10(x)
- log(1 + x)を計算(底はe)
np.log1p(x)
n [1]: import numpy as np
In [2]: np.log(np.e) # np.eでネイピア数e
Out[2]: 1.0
In [3]: a = np.array([1., 2., np.e**2, 10])
In [4]: np.log(a) # 配列を指定することもできる。(他の数学関数も同様)
Out[4]: array([ 0. , 0.69314718, 2. , 2.30258509])
In [5]: b = np.array([1., 2., 4., 7])
In [6]: np.log2(b)
Out[6]: array([ 0. , 1. , 2. , 2.80735492])
In [7]: c = np.array([1., 10., 20., 100])
In [8]: np.log10(c)
Out[8]: array([ 0. , 1. , 1.30103, 2. ])
In [9]: np.log1p(a)
Out[9]: array([ 0.69314718, 1.09861229, 2.12692801, 2.39789527])
底を他の値に変えたい時は、その変えたい底を真数とする対数で割ります。
In [10]: np.log(2)/np.log(4) # log4(2)がこれでできる。
Out[10]: 0.5
In [11]: np.log(9)/np.log(3) # log3(9)
Out[11]: 2.0
双曲線関数(hyperbolic)
双曲線関数とは、以下のように定義される2つの関数からできる一連の関数のことです。
sinhはハイパボリックサイン、coshはハイパボリックコサインなどと呼ばれます。
また、tanh(ハイパボリックタンジェント)は
のように定義されます。
形は全く違いますが、これらの関数は三角関数と似た性質をいくつか示すため、sin, cos, tanのような語がついてきています。
詳しい解説は以下のサイトを参照してください。
これもNumPyの関数として呼び出すことが可能です。
逆関数としてnp.arcsinh(x)
,np.arccosh(x)
,np.arctanh(x)
も存在します。
In [12]: np.sinh(2)
Out[12]: 3.6268604078470186
In [13]: np.cosh(2)
Out[13]: 3.7621956910836314
In [14]: np.tanh(2)
Out[14]: 0.9640275800758169
In [15]: np.sinh(-1)
Out[15]: -1.1752011936438014
In [16]: np.cosh(-1)
Out[16]: 1.5430806348152437
In [17]: np.tanh(-1)
Out[17]: -0.76159415595576485
In [18]: np.arcsinh(2)
Out[18]: 1.4436354751788103
In [19]: np.arccosh(1)
Out[19]: 0.0
In [20]: np.arctanh(0.7)
Out[20]: 0.86730052769405319
切り捨て、切り上げ、四捨五入
概数を求めるメソッドには、以下のようなものがあります。
- 切り捨て
np.floor()
- 切り捨て
np.trunc()
- 切り上げ
np.ceil()
- 四捨五入
np.round()
- 四捨五入
np.around()
- 四捨五入
np.rint()
- 0に近い方向で整数をとる
np.fix()
In [1]: import numpy as np
In [2]: a = np.array([-1.8, -1.4, -1.0, -0.6, -0.2, 0., 0.2, 0.6, 1.0, 1.4, 1.8])
In [3]: np.floor(a) # 切り捨て(値が小さい方の整数にする)
Out[3]: array([-2., -2., -1., -1., -1., 0., 0., 0., 1., 1., 1.])
In [4]: np.trunc(a) # 切り捨て(小数部分を切り捨てる)
Out[4]: array([-1., -1., -1., -0., -0., 0., 0., 0., 1., 1., 1.])
In [5]: np.ceil(a) # 切り上げ(大きい方の整数にする)
Out[5]: array([-1., -1., -1., -0., -0., 0., 1., 1., 1., 2., 2.])
In [6]: np.round(a) # 四捨五入
Out[6]: array([-2., -1., -1., -1., -0., 0., 0., 1., 1., 1., 2.])
In [7]: np.around(a) # 四捨五入
Out[7]: array([-2., -1., -1., -1., -0., 0., 0., 1., 1., 1., 2.])
In [8]: np.rint(a) # 四捨五入
Out[8]: array([-2., -1., -1., -1., -0., 0., 0., 1., 1., 1., 2.])
In [9]: np.fix(a) # 0に近い方向の整数をとる
Out[9]: array([-1., -1., -1., -0., -0., 0., 0., 0., 1., 1., 1.])
複素数
NumPyは複素数も扱うことができます。虚部のところにj
を添えるだけです。また、複素数に関する関数として実部を返すnp.real()
,虚部を返すnp.imag()
,複素共役(虚部の符号を反転させたもの)を返すnp.conj()
があります。
複素数は、音波の位相やコンピューターグラフィックスでよく使われるクォータニオンなどに便利な概念です。
In [6]: import numpy as np
In [7]: a = 1 + 2j # 1 + 2iの複素数
In [8]: b = -2 + 1j # -2 + iの複素数。1を忘れないようにする
In [9]: np.real(a) # aの実部は1
Out[9]: 1.0
In [10]: np.imag(a) # aの虚部は2
Out[10]: 2.0
In [6]: a+b # 複素数の計算と同じように、実部同士、虚部同士を足し合わせる。
Out[6]: (-1+3j)
In [7]: a*b
Out[7]: (-4-3j)
In [8]: a/b
Out[8]: (-0-1j)
In [9]: np.conj(a) # 複素共役を返す
Out[9]: (1-2j)
絶対値
絶対値をとる関数もあります。これには2つあって、np.fabs
とnp.absolute()
があります。np.absolute()
の略記でnp.abs()
もあります。配列を引数として指定すると各要素の絶対値が返されます。この2つの関数の違いは複素数を引数として指定できるか否かです。
np.absolute()
は複素数の絶対値を返すことができます。np.fabs()
はできません。
In [1]: import numpy as np
In [2]: a = -2.5
In [3]: np.absolute(a)
Out[3]: 2.5
In [4]: np.fabs(a)
Out[4]: 2.5
In [5]: b = -2 + 3j # 複素数でやってみる。
In [6]: np.abs(b) # np.absはnp.absolute()の略記。
Out[6]: 3.6055512754639891
In [7]: np.fabs(b) # np.fabs()では、複素数の絶対値を計算することができない。
---------------------------------------------------------------------------
(エラーメッセージが表示される)
In [8]: c = np.array([-1, 2, -8, 12, 1+2j])
In [9]: np.abs(c) # 各々の要素の絶対値が返ってくる。
Out[9]: array([ 1. , 2. , 8. , 12. , 2.23606798])
数学的な定数の呼び出し
最後に数学でよく用いられる定数としてNumPyに設定されているものをみていきましょう。
どうやらeとπしかなさそうです。
どちらも呼び出す時は()
を必要とはしません。
定数 | NumPyでの関数 |
---|---|
ネイピア数e | np.e |
円周率π | np.pi |
In [1]: import numpy as np
In [2]: np.e
Out[2]: 2.718281828459045
In [3]: np.pi
Out[3]: 3.141592653589793