Remrinのpython攻略日記

python3に入門しました。python3についてあれこれとサンプルコードとか。

NumPyの使い方(16) 行列matrix

NumPyのmatrixについて。
 

class 種類 次元
ndarray 配列 次元は自由
matrix 行列 2次元に固定

 
ndarrayでは行列の積を表すときにdot()を呼びだすが、
matrixでは「*」や「**」で行列の積などを表せる。
その他の使い方はndarrayと同様のようです。
 

import numpy as np

a1 = np.array([[1, 2], [3, 4]])
a2 = np.array([[1, 1], [1, 1]])

print(a1 * a2)    #同じ位置の要素どうしの積
# [[1 2]
#  [3 4]]

print(a1.dot(a2)) # 内積
# [[3 3]
#  [7 7]]

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

print(m1 * m2)
# [[3 3]
#  [7 7]]

print(m1 ** -1)  # 逆行列(1)
# [[-2.   1. ]
#  [ 1.5 -0.5]]

print(m1.I)      # 逆行列(2)
# [[-2.   1. ]
#  [ 1.5 -0.5]]

m3 = np.matrix([[1, 3], [-2, -4]])
P = (np.linalg.eig(m3))[1]         # 正規化された固有ベクトルから作った対角化行列
print(P)
# [[ 0.83205029 -0.70710678]
#  [-0.5547002   0.70710678]]

PiAP = P.I * m3 * P  # 対角化された行列
PiAP = PiAP.round(3) # 見やすくするため四捨五入
print(PiAP)
# [[-1.  0.]
#  [-0. -2.]]

print((PiAP)**2)
# [[ 1.  0.]
#  [ 0.  4.]]

print((PiAP)**3)
# [[-1.  0.]
#  [-0. -8.]]

# ndarrayでの内積の書き方
a3 = np.array(PiAP)
print(PiAP.dot(PiAP).dot(PiAP).dot(PiAP))
# [[  1.   0.]
#  [  0.  16.]]

 
行列の積などを多用するプログラムのときはmatrixを用いると見やすく書けそう。
 

操作・演算 ndarray matrix
* 対応要素の積 内積matrix product
** 各要素の2乗 行列の2乗
*-1 各要素の逆数 逆行列inverse
I属性 なし 逆行列inverse
H属性 なし 共役転置conjugate transpose

 
matrixは2次元固定なので次元削減の操作にも一部違いがあります。
axisを指定したmean()だと、2次元(ndim=2)のままです。

m1 = np.matrix([5, 1])
print(m1)         # [[5 1]]
print(m1.shape)   # (1, 2)
print(m1.mean(1)) # [[3]]        # 2次元のまま
print(m1.mean(0)) # [[ 5.  1.]]
print(m1.mean())  # 3.0

 
特にこだわりがなければ、matrixを使わずに、ndarrayだけで必要な操作ができるみたいです。

NumPyの使い方(15) ブロードキャスト

NumPyのブロードキャストについて。
 
配列の次元、大きさ(要素数)などが異なっていても配列どうしやスカラーの演算ができる。
ブロードキャストができるのは、2つの配列のshapeを最終軸から順に比較していき、同じ大きさか、一方が1であるかチェック。
1つでも該当しない軸があるとブロードキャストできない。
 
f:id:rare_Remrin:20170515125924p:plain
 
例をいくつか。

import numpy as np

a1 = np.array([[1, 2, 3], [4, 5, 6]])
print(a1)     # shape:(2, 3)
# [[1 2 3]
#  [4 5 6]]

print(a1 + 1)
# [[2 3 4]
#  [5 6 7]]

print(a1 + [1, 1, 1]) # shape:(3,)
# [[2 3 4]
#  [5 6 7]]

#print(a1 + [1, 1])
# ValueError: operands could not be broadcast together with shapes (2,3) (2,) 

print(a1 + [[1], [10]]) # shape:(2, 1)
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

a1 = np.arange(0, 600, 100).reshape(2, 3, 1)
print(a1)
# [[[0]
#   [100]
#   [200]]
#
#  [[300]
#   [400]
#   [500]]]

a2 = np.arange(12).reshape(3, 4)
print(a2)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(a1 + a2)
# [[[  0   1   2   3]
#   [104 105 106 107]
#   [208 209 210 211]]
#
#  [[300 301 302 303]
#   [404 405 406 407]
#   [508 509 510 511]]]

 
ブロードキャスト可能かどうか

b = (lambda a1, a2:all(i==1 or j==1 or i==j for i, j 
          in zip(a1.shape[::-1], a2.shape[::-1])))

a1 = np.arange(6)

print(b(a1.reshape(2, 3, 1), a1.reshape(3, 2))) # True
print(b(a1.reshape(2, 3, 1), a1.reshape(2, 3))) # False
print(b(a1.reshape(2, 3, 1), a1.reshape(1, 6))) # True
print(b(a1.reshape(2, 3, 1), a1.reshape(6, 1))) # False
print(b(a1.reshape(2, 1, 3), a1.reshape(2, 3))) # True
print(b(a1.reshape(3, 1, 2), a1.reshape(6,)))   # False
print(b(a1.reshape(2, 1, 3), np.zeros(3)))      # True
print(b(a1.reshape(2, 1, 3), np.array(10)))     # True スカラー(0次元)

NumPyの使い方(14) 繰り返し

NumPyの繰り返しrepeat()、tile()について。
 

np.repeat()

 配列の要素を繰り返す。
 axisを省略すると1次元にflattenされる。

import numpy as np

a1 = np.arange(4)
print(a1.repeat(2))
#  [0 0 1 1 2 2 3 3]

print(a1.repeat([3, 2, 1, 0]))
# [0 0 0 1 1 2]

a2 = np.arange(6).reshape(2, 3)
print(a2.repeat(2, axis=0))
# [[0 1 2]
#  [0 1 2]
#  [3 4 5]
#  [3 4 5]]

print(a2.repeat(2, axis=1))
# [[0 0 1 1 2 2]
#  [3 3 4 4 5 5]]

print(a2.repeat([1, 2, 3], axis=1))
# [[0 1 1 2 2 2]
#  [3 4 4 5 5 5]]

# axisを省略すると1次元化
print(a2.repeat(2))
# [0 0 1 ..., 4 5 5]

print(np.repeat(a2, 2)) # 関数でも表現できる
# [0 0 1 ..., 4 5 5]

 

np.tile()

タイル状に敷き詰める。

a1 = np.arange(4)
print(np.tile(a1, 2))
# [0 1 2 3 0 1 2 3]

print(np.tile(a1, (2, 3)))
# [0 1 2 3 0 1 2 3]
# [[0 1 2 ..., 1 2 3]
#  [0 1 2 ..., 1 2 3]]

print(np.tile(a1, (1, 2, 3)))
# [[[0 1 2 ..., 1 2 3]
#   [0 1 2 ..., 1 2 3]]]

a2 = np.arange(6).reshape(2, 3)
print(np.tile(a2, 2))
# [[0 1 2 0 1 2]
#  [3 4 5 3 4 5]]

print(np.tile(a2, (3, 2)))
# [[0 1 2 0 1 2]
#  [3 4 5 3 4 5]
#  [0 1 2 0 1 2]
#  [3 4 5 3 4 5]
#  [0 1 2 0 1 2]
#  [3 4 5 3 4 5]]

 

Numpyの使い方(13) 結合・分割

Numpyの配列の結合・分割について。
 

np.concatenate()

 2個以上の配列を軸指定して結合する。
 軸指定オプションのaxisはデフォルトが0
 マスクは保存されない。(マスクについては別の記事で)
 

import numpy as np

a1 = np.array([[1, 2, 3], [4, 5, 6]])
a2 = np.array([[7, 8, 9], [0, 11, 12]])

print(np.concatenate([a1, a2], axis=0))
# [[  1  2  3]
#  [  4  5  6]
#  [  7  8  9]
#  [ 10 11 12]]

print(np.concatenate([a1, a2], axis=1))
# [[ 1  2  3   7  8  9]
#  [ 4  5  6  10 11 12]]

 
・軸axisの指定はすでに存在している軸のみ。
 (Join a sequence of arrays along an existing axis.)
 1次元配列:axis=0
 2次元配列:axis=0, axis=1
 3次元配列:axis=0, axis=1, axis=2
 N次元配列:axis=[0, N)  0以上N未満

v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])

print(np.concatenate([v1, v2], axis=0))
# [1 2 3 4 5 6]

# print(np.concatenate([v1, v2], axis=1))
# IndexError: axis 1 out of bounds [0, 1)

 
・結合の方向にかかわらず、配列の次元が同じでないと結合できない。

a1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 2次元配列
a2 = np.array([10, 11, 12])                      # 1次元配列
print(np.concatenate([a1, a2], axis=0))
# ValueError: all the input arrays must have same number of dimensions

 
行列(2次元配列)にベクトル(1次元配列)を結合させるとエラーだが、
ベクトルを2次元で表記すると結合できる。

a1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
a2 = np.array([[10, 11, 12]])   # 2重の[[]]でベクトルを2次元で表記

print(np.concatenate([a1, a2], axis=0))
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]

print(np.concatenate([a1, a2.T], axis=1))
# [[ 1  2  3 10]
#  [ 4  5  6 11]
#  [ 7  8  9 12]]

 
・ベクトル(1次元配列)を行列(2次元配列)に変換する方法

# ndim=1 のベクトルを ndim=2の横ベクトルに変換
v1 = np.array([1, 2, 3])
v2 =np.reshape(v1, (1, v1.shape[0]))
print(v2.shape)  # (1, 3)
print(v2)        # [[1 2 3]]

# ndim=1 のベクトルを ndim=2の縦ベクトルに変換
v1 = np.array([1, 2, 3])
v3 =np.reshape(v1, (v1.shape[0], 1))
print(v3.shape)  # (3, 1)
print(v3)
# [[1]
#  [2]
#  [3]]

 
・shapeが異なっていても結合できるが、結合方向は揃える。

a1 = np.array([[1, 2, 3], [4, 5, 6]])
a2 = np.array([[7, 8, 9], [10, 11, 12], [13, 14, 15]])

print(np.concatenate([a1, a2], axis=0))
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]
#  [13 14 15]]

#print(np.concatenate([a1, a2], axis=1))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly

 

np.vstack(), np.hstack()、np.row_stack()、np.column_stack()、np.dstack()

 concatenate()は汎用で軸の指定をできるが、それぞれの軸に対応した関数もある。
 縦方向の結合:vstack()、row_stack()
 横方向の結合:hstack()、column_stack()
 深さ方向(axis=2)の結合:dstack()

a1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
a2 = np.array([[10, 11, 12]])   # 2重の[[]]でベクトルを2次元で表記

print(np.vstack([a1, a2]))
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]

print(np.hstack([a1, a2.T]))
# [[ 1  2  3 10]
#  [ 4  5  6 11]
#  [ 7  8  9 12]]

 
・dstack()の例

a1 = np.array([[1, 2, 3], [2, 3, 4]])
a2 = np.array([[5, 6, 7], [6, 7, 8]])

a1 = np.reshape(a1, (*a1.shape, 1))
a2 = np.reshape(a2, (*a2.shape, 1))

print(np.dstack([a1, a2]))   
# [[[1 5]
#   [2 6]
#   [3 7]]
#
#  [[2 6]
#   [3 7]
#   [4 8]]]

3次元配列って、思っていたのとかなり違う。
軸変換しないと脳内のイメージと全然あわないですね。
 
f:id:rare_Remrin:20170513132338p:plain
 
イメージしていたのはこれです。

a1 = np.array([[1, 2, 3], [2, 3, 4]])
a2 = np.array([[5, 6, 7], [6, 7, 8]])
a1 = np.reshape(a1, (1, *a1.shape))
a2 = np.reshape(a2, (1, *a2.shape))

print(a1)
# [[[1 2 3]
#   [2 3 4]]]

print(np.vstack([a1, a2]))   
# [[[1 2 3]
#   [2 3 4]]
#
#  [[5 6 7]
#   [6 7 8]]]

 

np.c_(), np.r_()

 concatenate()の代わりに使えて、スライスからも配列を生成できる。

a1 = np.arange(6).reshape(2, 3)
a2 = np.arange(100, 700, 100).reshape(2, 3)

print(np.r_[a1, a2])
# [[  0   1   2]
#  [  3   4   5]
#  [100 200 300]
#  [400 500 600]]

print(np.c_[a1, a2])
# [[  0   1   2 100 200 300]
#  [  3   4   5 400 500 600]]

print(np.c_[np.r_[a1, a2, a1], np.arange(6)])
# [[  0   1   2   0]
#  [  3   4   5   1]
#  [100 200 300   2]
#  [400 500 600   3]
#  [  0   1   2   4]
#  [  3   4   5   5]]


# スライスから配列を作れる
print(np.r_[:4, 10, 10, 4:0:-1])
# [ 0  1  2  3 10 10  4  3  2  1]

print(np.c_[:4, [10]*4, 4:0:-1])
# [[ 0 10  4]
#  [ 1 10  3]
#  [ 2 10  2]
#  [ 3 10  1]]

 

np.split()

 配列の分割。

a = np.arange(12).reshape(6, 2)
print(a)
# [[ 0  1]
#  [ 2  3]
#  [ 4  5]
#  [ 6  7]
#  [ 8  9]
#  [10 11]]

a1, a2, a3 =np.split(a, [1, 3]) #1行目と3行目の手前でsplit
print(a1)
# [[0 1]]

print(a2)
# [[2 3]
#  [4 5]]

print(a3)
# [[ 6  7]
#  [ 8  9]
#  [10 11]]

a1, a2 =np.split(a, 2, axis=0) # 2等分
print(a1)
# [[0 1]
#  [2 3]
#  [4 5]]
print(a2)
# [[ 6  7]
#  [ 8  9]
#  [10 11]]

a1, a2 =np.split(a, 2, axis=1) # 2等分
print(a1)
# [[ 0]
#  [ 2]
#  [ 4]
#  [ 6]
#  [ 8]
#  [10]]
print(a2)
# [[ 1]
#  [ 3]
#  [ 5]
#  [ 7]
#  [ 9]
#  [11]]

 
その他の分割関数

np.hsplit() hstackの逆
np.vsplit() vstackの逆
np.dsplit() dstackの逆

NumPyの使い方(12) 乱数、random

乱数を発生させるライブラリは主に2つ。

randomライブラリとNumPyのrandom
2つのライブラリの一番の違いは乱数の発生個数。

乱数の発生個数

randomモジュール :乱数1個
numpyは配列の形をsize=~の形のキーワード引数で乱数の個数を指定できる。
size 省略  →1個の乱数
size = 数値 →1次元配列
size = タプル→多次元配列

乱数の初期化

random.seed(数値)
np.random.seed(数値)
 
同じ初期値にすると、再現性のある乱数列になる。
 

小数(一様uniform)

0~1の乱数

random.random() 0~1の乱数乱数を1個生成。
np.random.rand(size) 0~1の乱数列。配列生成後に再計算すると範囲を変えられる

 
範囲を指定した乱数

random.uniform(low, high) low以上high未満の一様乱数を1個生成
np.random.uniform(low, high, size) low以上high未満の一様乱数

 

import numpy as np
import random

print(random.random())
# 0.9733563537374995

print(np.random.rand(3))
# [ 0.69962497  0.61950126  0.7944733 ]

print(np.random.rand(2, 3))
# [[ 0.29315148  0.06560949  0.56110618]
#  [ 0.62784039  0.19218867  0.07087768]]

np.random.uniform(1, 10, 3) 1以上10未満の一様乱数3個の配列。
# [ 8.77776521  4.21775806  9.269332  ]

 
・乱数で円周率を求める:
f:id:rare_Remrin:20170509174416p:plain
サンプルコードはこちら 
 
ランダムウォーク
 0~1の乱数を生成し、0.5以上なら+1、0.5未満なら-1を加えていく。

# coding: utf-8

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(1)            # 乱数の初期化。
w = np.random.rand(1000)     # 1000個の乱数生成
w = np.where(w > 0.5, 1, -1) # 0.5以上は1に、0.5未満は-1に変更
w = w.cumsum()               # 累積和を取る

print(w.min())    # -11
print(w.max())    # 35

print(w.argmin()) # 64   最初に-11になったインデックス
print(w.argmax()) # 368  最初に35になったインデックス

plt.plot(np.arange(1000), w) # 折れ線グラフとして表示
plt.scatter(w.argmin(), w.min(), marker="D", c="r")
plt.scatter(w.argmax(), w.max(), marker="D", c="r")
plt.text(w.argmin(), w.min(), "min", fontsize=16)
plt.text(w.argmax(), w.max(), "max", fontsize=16)
plt.show()

 
株価の変動のようなグラフになりますね。
seed()の値をいろいろ変えてみると面白そう。
 
f:id:rare_Remrin:20170516223745p:plain
 

小数(分布が一様ではない)

正規分布(ガウス分布)に従う乱数 normal distribution

random.normalvariate(mu, sigma) mu:平均、sigma標準偏差
random.gauss(mu, sigma) normalvariateより少し速い
np.random.normal(loc, scale=1.0, size) loc:平均、scale:標準偏差

 
・標準正規分布に従う standard normal distribution

np.random.randn(size) 標準正規分布(平均0、標準偏差1)

 
・β分布(ベータ分布)

random.betavariate(alpha, beta) β分布の乱数
np.random.beta(a, b, size)

 
・γ分布(ガンマ分布)

gammavariate(alpha, beta) alpha>0, beta>0
random.gammavariate(alpha, beta) ガンマ分布の乱数

 
・カイ2乗分布

np.random.chisquare(df,size) df:自由度

 
・指数分布

random.expovariate(lambd) lambdaは予約語なのでlambd
np.random.exponential(scale, size) scale:β=1/λ

 
・対数分布

random.lognormvariate(mu, sigma) 対数分布の乱数
np.random.lognormal(mean, sigma, size) mean:平均、sigma標準偏差

 

print(np.random.randn(3, 3))           #標準正規分布の3×3配列
# [[-0.52434526  0.16597271 -2.22295048]
#  [ 0.46995083 -0.64576356 -2.73155503]
#  [ 1.04575168  0.05712791 -0.46522963]]
               
print(np.random.normal(10, 5, (2, 3)))  #平均10、標準偏差5、2行3列
# [[ 15.15167613   9.56576376   5.79689885]
#  [ 18.18351327  17.17248557   3.4675871 ]]

 
mu(平均)=20、sd(標準偏差)=5の乱数を10000回発生させ、
ヒストグラム(青)で表示し、正規分布のグラフ(赤)と比較する。

import numpy as np
import matplotlib.pyplot as plt
mu, sd = 20, 5
s = np.random.normal(mu, sd, 10000)
count, bins, ignored = plt.hist(s, 40, normed=True)
plt.plot(bins, 1/(sd * np.sqrt(2 * np.pi)) *
               np.exp( - (bins - mu)**2 / (2 * sd**2) ),
         linewidth=2, color='r')
plt.show()

 
f:id:rare_Remrin:20170427015230p:plain
 

整数

random.randint(low, high) low以上、high以下の整数の乱数を1個生成
random.randrange(low, high, step) low以上、high未満、stepの乱数を1個生成
np.random.randint(low, high, size) low以上、high未満
np.random.random_integers 非推奨

 

np.random.randint(1, 10, 2)         #1以上10未満の整数2個のndarrayを生成。
np.random.randint(1, 10, (2, 3)    #2行3列のndarrayを生成。
np.random.randint(2, size=8)        #highを省略すると、lowの値をhigh扱い。
# array([1, 0, 0, 0, 1, 1, 1, 0])
np.random.randint(1, size=8)        #1未満の整数、つまり0のみ。
# array([0, 0, 0, 0, 0, 0, 0, 0])

 
・2項分布に従う

np.random.binomial(n, p, size) n:試行回数 p:確率

 

# コインを100回投げて表が出た回数
a = np.random.binomial(100, 0.5)
print(a)   # 48

#コインを100回投げて表が出た回数を10セット
print(np.random.binomial(100, 0.5, (2, 5))) 
# [[53 43 48 49 44]
#  [48 47 55 44 60]]

選択

random.choice(seq) seqから1個選択
np.random.choice(a) aから複数個選択

np.random.choice(a, size=None, replace=True, p=None)
a:1次元のndarrayまたはリストの場合、その要素からチョイス。
 数値の場合はnp.arange()で要素を準備
replace True:重複あり、False:重複なし
p:和が1となる重みづけのリスト。
 

seq1=[0123]
random.choice(seq1)              #1回チョイス
random.choice("hello")           #5文字の中から1文字チョイス
np.random.choice(seq1, 4)        #重複ありで4回チョイスした配列
np.random.choice([2, 4, 6],2)   #重複ありで2回チョイスした配列
np.random.choice([0, 1], (3, 3)) #size3×3の配列に0,1を埋める
np.random.choice(5, 2)           #np.randint(0, 5, 2)と同義

 
np.random.choiceで描いたバーンスレイのシダ。サンプルコードはこちら
f:id:rare_Remrin:20170506224421p:plain
 

シャッフル

random.shuffle(list) listをシャッフルする。返り値はNone
np.random.shuffle(x) listまたはarrayをシャッフルする。返り値はNone

 

arr = np.arange(10)
np.random.shuffle(arr)      #[1 7 5 2 9 4 3 6 0 8]

 

サンプリング

random.sample(population, k) populationの中からk個選んだリストを返す。
  populationはシーケンスまたはset。ハッシュ可能でなくてもよい。値はダブり可

random.sample("abcd", 3)    #['d', 'c', 'a']
random.sample("abcd", 6)    #ValueError: Sample larger than population
random.sample(range(1000), k=20)   #0-999から20個選ぶ

 
参考:numpyのドキュメント

NumPyの使い方(11) 行列計算

NumPyの行列計算について
 

内積

内積はnp.dot()関数を使うかarray.dot()メソッドを使うか。
内積は順序によって結果が異なる。

import numpy as np

a1 = np.ones([2, 2], dtype=int)
a2 = np.arange(1, 5).reshape(2, 2)

print(a1)
# [[1 1]
#  [1 1]]

print(a2)
# [[1 2]
#  [3 4]]

# 行列の内積(1)
print(np.dot(a1, a2))
# [[4 6]
#  [4 6]]

# 行列の内積(1)
print(a1.dot(a2))
# [[4 6]
#  [4 6]]

# 行列の内積(3)
print(np.dot(a2, a1))
# [[3 3]
#  [7 7]]

 

線形代数関数

numpy.linalgライブラリに線形代数の関数がある。
 

array.T 転置行列
diag 正方行列の対角成分を抜き出す。また、1次元配列からはそれを対角成分とする正方行列を作る。
dot 内積
cross 外積
trace 対角成分の和
linalg.norm ノルム。ベクトルの長さ
linalg.det 行列式
linalg.eig 固有値と固有行列
linalg.inv 逆行列
pinv 疑似逆行列
qr QR分解
svd 特異値分解
linalg.solve 連立方程式を解く
lstsq 最小二乗法

 

a1 = np.array([[1, 2],[3, 4]])
print(a1)
# [[1 2]
#  [3 4]]

# 転置行列
print(a1.T)
# [[1 3]
#  [2 4]]

# 対角成分
print(np.diag(a1))  # [1 4]
print(np.diag([1, 2, 3, 4, 5]))
# [[1 0 0 0 0]
#  [0 2 0 0 0]
#  [0 0 3 0 0]
#  [0 0 0 4 0]
#  [0 0 0 0 5]]

# trace
print(np.trace(a1))      # 5

# 行列式     
print(np.linalg.det(a1)) # -2.0

# 固有ベクトルと固有値
print(np.linalg.eig(a1))
# (array([-0.37228132,  5.37228132]), array([[-0.82456484, -0.41597356],
#        [ 0.56576746, -0.90937671]]))

# 逆行列
print(np.linalg.inv(a1))
# [[-2.   1. ]
#  [ 1.5 -0.5]]

# 連立方程式 x+2y=5, 3x+4y=13を解く
print(np.linalg.solve(a1, [5, 13])) # [3. 1. ] x=3, y=1

 

NumPyの使い方(10) 集合関数

NumPyの集合関数について。 
 
python標準のset型も参照。
 
1次元配列を対象とした集合関数

unique(x) 重複を除外し、ソートした配列
in1d(x,y) xの各要素がyに存在するか
intersect1d(x, ) 共通部分。積集合
union1d(x, y) 和集合
setdiff1d(x, y) 差集合
setxor1d(x, y) 排他的論理和

 

np.unique()

1次元の配列から重複を取り除き、ソートした配列を返す。
python標準のsorted(set(seq))と同様の働き。

import numpy as np

a1 = np.array([1, 3, 2, 0, 1, 2, 2, 1])
print(np.unique(a1))  # [0 1 2 3]

 
return_index=Trueとすると初回のインデックスを返す。
return_counts=Trueとすると、重複している回数を返す。

print(np.unique(a1, return_index=True))
# (array([0, 1, 2, 3]), array([3, 0, 2, 1], dtype=int32))

print(np.unique(a1, return_counts=True))
# (array([0, 1, 2, 3]), array([1, 3, 3, 1]))

 

in1d()

要素の存在判定をする関数

a1 = np.array([1, 3, 5, 5, 5, 1])
print(np.in1d(a1, [1, 2, 3]))
# [ True  True False False False  True]

print(np.in1d([1, 2, 3], a1))
# [ True False  True]