numpy 概要

効率的な数値計算のためのライブラリ。

インストール

$ pip install numpy

使い方

import numpy as np

配列・行列の生成

list を numpy 配列に変換

l = [1,2,3,4,5]
a = np.array(l)
# array([1, 2, 3, 4, 5])

多次元 list を numpy 行列に変換

# 行ベクトル
np.matrix([0, 1])
"""
matrix([[0, 1]])
"""

# 列ベクトル
np.matrix([
	[0],
	[1]
])
"""
matrix([[0],
        [1]])
"""

# 行列
np.matrix([
	[0, 1, 2],
	[3, 4, 5]
])
"""
matrix([[0, 1, 2],
        [3, 4, 5]])
"""

区間を指定した個数に等間隔で分割する配列

$a \le x \le b$ の区間(両端含む)を指定した個数に分割

a, b = 1, 10
np.linspace(a, b, 10)
# array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])
np.linspace(a, b, 19)
# array([ 1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5,  5. ,  5.5,  6. ,
#        6.5,  7. ,  7.5,  8. ,  8.5,  9. ,  9.5, 10. ])

区間内の等差数列

初項 $a$、公差 $d$、上限 $b$($b$ 自身は含まない)の等差数列を作成

a, b = 1, 10
np.arange(a, b, 1.0)
# array([1., 2., 3., 4., 5., 6., 7., 8., 9.])
np.arange(a, b+0.000001, 1.0)
# array([1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])

乱数配列

# 平均0、標準偏差1の正規分布
rand = np.random.normal(loc=0, scale=1.0, size=(3,4))
"""
array([[ 0.25231664,  0.57895262,  0.59728289,  0.37939539],
       [-0.80000888, -0.36862112, -0.772507  ,  0.89776578],
       [-2.49653143,  1.17558449, -0.37644545,  1.50055032]])
"""

# 0以上3未満の整数
np.random.randint(3, size=(3,4))
"""
array([[0, 1, 1, 2],
       [0, 1, 2, 2],
       [1, 0, 0, 1]])
"""

# 0以上1未満の小数
np.random.rand(3,4)
"""
array([[0.58274554, 0.41312968, 0.34026029, 0.58275797],
       [0.58989403, 0.04602324, 0.06885702, 0.09617708],
       [0.54617384, 0.94229429, 0.91238302, 0.33197529]])
"""

メッシュ(格子列)

x = np.array(range(5))
y = np.array(range(3, 6))
XX, YY = np.meshgrid(x, y)
"""
>>> XX
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])
>>> YY
array([[3, 3, 3, 3, 3],
       [4, 4, 4, 4, 4],
       [5, 5, 5, 5, 5]])
"""

行列の演算

m1 = np.matrix([
	[1, 2],
	[3, 4]
])
m2 = np.matrix([
	[-1, 3],
	[2, 1]
])
m3 = np.matrix([
	[-1, 3, 2],
	[2, 1, -1]
])
m4 = np.matrix([
	[1, 2],
	[3, 4],
	[5, 6]
])

行列の積

# 行列の積
m1 * m2
"""
matrix([[ 3,  5],
        [ 5, 13]])
"""
m1 * m3
"""
matrix([[ 3,  5,  0],
        [ 5, 13,  2]])
"""
m3 * m4
"""
matrix([[18, 22],
        [ 0,  2]])
"""
m4 * m3
"""
matrix([[ 3,  5,  0],
        [ 5, 13,  2],
        [ 7, 21,  4]])
"""

# 行列の整数乗(各成分の累乗ではなく、行列としての累乗)
m1 ** 2
"""
matrix([[ 7, 10],
        [15, 22]])
"""
m1 ** 3
"""
matrix([[ 37,  54],
        [ 81, 118]])
"""

転置行列

m1.T
"""
matrix([[1, 3],
        [2, 4]])
"""

逆行列

m1.I
"""
matrix([[-2. ,  1. ],
        [ 1.5, -0.5]])
"""

固有値

A = np.matrix([
	[1, 2],
	[3, 4]
])

lmd, U = np.linalg.eig(A)
"""
lmd: 固有値
	array([-0.37228132,  5.37228132])
U: 固有ベクトルを(lmd と対応する並び順で)列ベクトルとして並べた行列
	matrix([[-0.82456484, -0.41597356],
	        [ 0.56576746, -0.90937671]])
"""

lmd1, lmd2 = lmd[0], lmd[1]
u1, u2 = U[:,0], U[:,1]

# 検算
A * u1 - lmd1 * u1 < 1e-10
A * u2 - lmd2 * u2 < 1e-10
"""
matrix([[ True],
        [ True]])
matrix([[ True],
        [ True]])
"""

# おまけ:固有ベクトル行列 U による A の対角化
U.I * A * U
"""
matrix([[-3.72281323e-01,  8.23749941e-16],
        [ 3.53579641e-16,  5.37228132e+00]])
"""

各成分の演算

# 和
m2 + m1
"""
matrix([[0, 5],
        [5, 5]])
"""

# 差
m2 - m1
"""
matrix([[-2,  1],
        [-1, -3]])
"""

# 積(アダマール積:成分どうしの積)
np.multiply(m2, m1)  # m2 * m1 は使えない!(行列の積が計算されてしまう)
"""
matrix([[ 8, 10],
        [ 5,  8]])
"""

# 商
m2 / m1
"""
matrix([[-1.        ,  1.5       ],
        [ 0.66666667,  0.25      ]])
"""

# 商(小数点切り捨て)
m2 // m1
"""
matrix([[-1,  1],
        [ 0,  0]])
"""

# 累乗
np.power(m2, m1)
"""
matrix([[-1,  9],
        [ 8,  1]])
"""

結合

m1 = np.matrix([
	[0, 1, 2],
	[3, 4, 5]
])
m2 = np.matrix([
	[6, 7, 8],
	[9, 10, 11]
])
v_r = np.matrix([12, 13, 14])
v_c = np.matrix([
	[15],
	[16]
])

# 縦に結合
np.concatenate((m1, m2, v_r), axis=0)
"""
matrix([[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11],
        [12, 13, 14]])
"""

# 横に結合
np.concatenate((m1, m2, v_c), axis=1)
"""
matrix([[ 0,  1,  2,  6,  7,  8, 15],
        [ 3,  4,  5,  9, 10, 11, 16]])
"""

条件判定

a = np.arange(10, 100+10, 10)
np.random.shuffle(a)
# array([ 70,  60,  50,  30,  80,  40,  90,  20,  10, 100])

# 条件を満たすインデックスを抽出
np.where(a<50)[0]
# array([3, 5, 7, 8])

# 条件を満たすものと満たさないもので別の処理を適用
np.where(a<50, a*10, a/10)
# array([  7.,   6.,   5., 300.,   8., 400.,   9., 200., 100.,  10.])

AND, OR のときは括弧と &,| を使う:

np.where((a<75) & (25<a))[0]
# array([0, 1, 2, 3, 5])
np.where((a<=25) | (75<=a))[0]
# array([4, 6, 7, 8, 9])

通常の関数をユニバーサル関数に変換

# 1つの引数から1つの結果を出力する関数
def myfunc1to1(x):
	if x >= 0:
		return x * 10
	else:
		return x * -10

# 2つの引数から2つの結果を出力する関数
def myfunc2to2(x, y):
	return x+y, x-y

# 2つの引数から1つの結果を出力する関数
def myfunc2to1(x, y):
	return x+y-1

# 1つの引数から2つの結果を出力する関数
def myfunc1to2(x):
	return x**2, x*2

np_myfunc1to1 = np.frompyfunc(myfunc1to1, nin=1, nout=1)
np_myfunc2to2 = np.frompyfunc(myfunc2to2, nin=2, nout=2)
np_myfunc2to1 = np.frompyfunc(myfunc2to1, nin=2, nout=1)
np_myfunc1to2 = np.frompyfunc(myfunc1to2, nin=1, nout=2)

a1 = np.array(range(9)) - 4
a2 = np.array(range(9)) * 0.1
"""
>>> a1
array([-4, -3, -2, -1,  0,  1,  2,  3,  4])
>>> a2
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])
"""

np_myfunc1to1(a1)
"""
array([40, 30, 20, 10, 0, 10, 20, 30, 40], dtype=object)
"""
np_myfunc2to2(a1, a2)
"""
(array([-4.0, -2.9, -1.8, -0.7, 0.4, 1.5, 2.6, 3.7, 4.8], dtype=object),
 array([-4.0, -3.1, -2.2, -1.3, -0.4, 0.5, 1.4, 2.3, 3.2], dtype=object))
"""
np_myfunc2to1(a1, a2)
"""
array([-5.0, -3.9, -2.8, -1.7, -0.6, 0.5, 1.6, 2.7, 3.8], dtype=object)
"""
np_myfunc1to2(a1)
"""
(array([16, 9, 4, 1, 0, 1, 4, 9, 16], dtype=object),
 array([-8, -6, -4, -2, 0, 2, 4, 6, 8], dtype=object))
"""