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つでも該当しない軸があるとブロードキャストできない。
例をいくつか。
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次元配列って、思っていたのとかなり違う。
軸変換しないと脳内のイメージと全然あわないですね。
イメージしていたのはこれです。
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 ]
・乱数で円周率を求める:
サンプルコードはこちら
・ランダムウォーク
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()の値をいろいろ変えてみると面白そう。
小数(分布が一様ではない)
・正規分布(ガウス分布)に従う乱数 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()
整数
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=[0、1、2、3] 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で描いたバーンスレイのシダ。サンプルコードはこちら
シャッフル
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]