NumPy クイックスタート
前提条件
Pythonの基礎知識が必要です。復習したい場合は、Pythonチュートリアルをご覧ください。
例題を実行するには、matplotlibNumPyに加えて、以下のものをインストールする必要があります。
学習者プロフィール
これは NumPy の配列の簡単な概要です。n 次元 (n 次元配列は表現され、操作できます。特に、一般的な関数を n 次元配列に適用する方法 (for ループを使用せずに) がわからない場合、または n 次元配列の軸と形状の特性を理解したい場合は、この記事が役立つかもしれません。
学習目標
読了後、あなたは以下のことができるようになるはずです。
-
NumPyにおける1次元配列、2次元配列、n次元配列の違いを理解する。
-
forループを使用せずに、n次元配列に線形代数演算を適用する方法を理解する。
-
n次元配列の軸と形状の特性を理解する。
基本事項
NumPy の主要オブジェクトは、同種の多次元配列です。これは、すべて同じ型の要素 (通常は数値) のテーブルであり、非負の整数のタプルによってインデックス付けされます。NumPy では、次元は軸と呼ばれます。
例えば、3D空間内の点の座標を表す配列には 、1つの軸があります。その軸には3つの要素が含まれているので、長さは3であると言えます。下の図の例では、配列には2つの軸があります。最初の軸の長さは2、2番目の軸の長さは3です。[1, 2, 1]
NumPy の配列クラスは と呼ばれますndarray。 という別名でも知られています array。は、1 次元配列のみを扱い、機能が少ないnumpy.array標準 Python ライブラリのクラス とは異なることに注意してくださいarray.array。 オブジェクトのより重要な属性は次のndarrayとおりです。
- ndarray.ndim
-
配列の軸数(次元数)。
- ndarray.shape
-
配列の次元。これは、各次元における配列のサイズを示す整数のタプルです。n 行 m 列の行列の場合、はになり
shapeます(n,m)。したがって、タプルの長さshapeは軸の数、 になりますndim。 - ndarray.size
-
配列の要素の総数。これは の要素の積に等しい
shape。 - ndarray.dtype
-
配列内の要素の型を記述するオブジェクト。dtypeは、標準のPython型を使用して作成または指定できます。さらに、NumPyは独自の型も提供しています。numpy.int32、numpy.int16、numpy.float64などがその例です。
- ndarray.itemsize
-
配列の各要素のサイズ(バイト単位)。たとえば、型の要素の配列は8 (=64/8)のサイズ
float64を持ち、型の要素の配列は 4 (=32/8) のサイズを持ちます。これは と同等です。itemsizecomplex32itemsizendarray.dtype.itemsize - ndarray.data
-
配列の実際の要素を含むバッファ。通常、配列の要素にはインデックス機能を使用してアクセスするため、この属性を使用する必要はありません。
例
import numpy as np
a = np.arange(15).reshape(3, 5)
a
array(0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14)
a.shape
(3, 5)
a.ndim
2
a.dtype.name
'int64'
a.itemsize
8
a.size
15
type(a)
<class 'numpy.ndarray'>
b = np.array([6, 7, 8])
b
array([6, 7, 8])
type(b)
<class 'numpy.ndarray'>
配列の作成
配列を作成する方法はいくつかあります。
例えば、array関数を使って通常のPythonリストやタプルから配列を作成できます。結果として得られる配列の型は、シーケンス内の要素の型から推測されます。
import numpy as np
a = np.array([2, 3, 4])
a
array([2, 3, 4])
a.dtype
dtype('int64')
b = np.array([1.2, 3.5, 5.1])
b.dtype
dtype('float64')
よくある間違いは、array引数として単一のシーケンスを指定するのではなく、複数の引数を指定して呼び出してしまうことです。
a = np.array(1, 2, 3, 4) # WRONG
Traceback (most recent call last):
...
TypeError: array() takes from 1 to 2 positional arguments but 4 were given
a = np.array([1, 2, 3, 4]) # RIGHT
arrayシーケンスのシーケンスを2次元配列に変換し、シーケンスのシーケンスのシーケンスを3次元配列に変換するなど、同様の処理を行います。
配列の型は、作成時に明示的に指定することもできます。
配列の要素は最初は不明な場合が多いが、サイズは既知である。そのため、NumPyには初期プレースホルダーコンテンツを持つ配列を作成するための関数がいくつか用意されている。これらの関数を使うことで、コストのかかる配列拡張の必要性を最小限に抑えることができる。
この関数はzerosゼロで埋め尽くされた配列を作成し、この関数は ones1で埋め尽くされた配列を作成し、この関数はempty 初期内容がランダムでメモリの状態に依存する配列を作成します。デフォルトでは、作成される配列のデータ型は です float64が、キーワード引数 を介して指定できますdtype。
np.zeros((3, 4))
array(0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.)
np.ones((2, 3, 4), dtype=np.int16)
array([1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1,
1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1], dtype=int16)
np.empty((2, 3))
array(3.73603959e-262, 6.02658058e-154, 6.55490914e-260], # may vary
[5.30498948e-313, 3.14673309e-307, 1.00000000e+000)
数値のシーケンスを作成するために、NumPy はarangePython の組み込み関数に類似した関数を提供しますrangeが、配列を返します。
np.arange(10, 30, 5)
array([10, 15, 20, 25])
np.arange(0, 2, 0.3) # it accepts float arguments
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
浮動小数点引数とともに使用する場合arange、浮動小数点の精度が有限であるため、取得される要素数を予測することは一般的に不可能です。そのため、linspaceステップの代わりに、必要な要素数を引数として受け取る関数を使用する方が通常は良いでしょう。
from numpy import pi
np.linspace(0, 2, 9) # 9 numbers from 0 to 2
array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])
x = np.linspace(0, 2 * pi, 100) # useful to evaluate function at lots of points
f = np.sin(x)
配列の出力
NumPyで配列を出力すると、ネストされたリストと同様の方法で表示されますが、レイアウトは次のようになります。
-
最後の軸は左から右に印刷され、
-
最後から2番目は上から下に印刷され、
-
残りの部分も上から下へ印刷され、各スライスは空行で区切られている。
1次元配列は行として、2次元配列は行列として、3次元配列は行列のリストとして印刷されます。
0 1 2 3 4 5]
b = np.arange(12).reshape(4, 3) # 2d array
print(b)
0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11
c = np.arange(24).reshape(2, 3, 4) # 3d array
print(c)
[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11
12 13 14 15]
[16 17 18 19]
[20 21 22 23a = np.arange(6) # 1d array
print(a)
[]
詳細については下記をご覧くださいreshape。
配列が大きすぎて印刷できない場合、NumPy は自動的に配列の中央部分をスキップし、角の部分のみを印刷します。
0 1 2 ... 9997 9998 9999]
print(np.arange(10000).reshape(100, 100))
0 1 2 ... 97 98 99]
[ 100 101 102 ... 197 198 199]
[ 200 201 202 ... 297 298 299]
...
[9700 9701 9702 ... 9797 9798 9799]
[9800 9801 9802 ... 9897 9898 9899]
[9900 9901 9902 ... 9997 9998 9999print(np.arange(10000))
[
この動作を無効にしてNumPyに配列全体を強制的に出力させるには、出力オプションを変更できますset_printoptions。
np.set_printoptions(threshold=sys.maxsize) # sys module should be imported
基本操作
配列に対する算術演算子は要素ごとに適用されます。新しい配列が作成され、その結果が格納されます。
a = np.array([20, 30, 40, 50])
b = np.arange(4)
b
array([0, 1, 2, 3])
c = a - b
c
array([20, 29, 38, 47])
b**2
array([0, 1, 4, 9])
10 * np.sin(a)
array([ 9.12945251, -9.88031624, 7.4511316 , -2.62374854])
a < 35
array([ True, True, False, False])
多くの行列言語とは異なり、NumPy配列では積演算子は要素ごとに作用します。行列積は、演算子(Python 3.5以降)または関数もしくはメソッド*を使用して実行できます。@dot
+=やなどの一部の操作は、*=新しい配列を作成するのではなく、既存の配列を変更するためにその場で動作します。
rg = np.random.default_rng(1) # create instance of default random number generator
a = np.ones((2, 3), dtype=int)
b = rg.random((2, 3))
a *= 3
a
array(3, 3, 3],
[3, 3, 3)
b += a
b
array(3.51182162, 3.9504637 , 3.14415961],
[3.94864945, 3.31183145, 3.42332645)
a += b # b is not automatically converted to integer type
Traceback (most recent call last):
...
numpy._core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
異なる型の配列を扱う場合、結果として得られる配列の型は、より一般的またはより正確な型に対応します(これはアップキャスティングと呼ばれる動作です)。
a = np.ones(3, dtype=np.int32)
b = np.linspace(0, pi, 3)
b.dtype.name
'float64'
c = a + b
c
array([1. , 2.57079633, 4.14159265])
c.dtype.name
'float64'
d = np.exp(c * 1j)
d
array([ 0.54030231+0.84147098j, -0.84147098+0.54030231j,
-0.54030231-0.84147098j])
d.dtype.name
'complex128'
配列内のすべての要素の合計を計算するなど、多くの単項演算は、ndarrayクラスのメソッドとして実装されています。
a = rg.random((2, 3))
a
array(0.82770259, 0.40919914, 0.54959369],
[0.02755911, 0.75351311, 0.53814331)
a.sum()
3.1057109529998157
a.min()
0.027559113243068367
a.max()
0.8277025938204418
デフォルトでは、これらの操作は配列の形状に関係なく、数値のリストとして配列に適用されます。ただし、axis パラメータを指定することで、配列の指定された軸に沿って操作を適用できます。
b = np.arange(12).reshape(3, 4)
b
array(0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 110, 4, 8])
b.cumsum(axis=1) # cumulative sum along each row
array(0, 1, 3, 6],
[ 4, 9, 15, 22],
[ 8, 17, 27, 38)
b.sum(axis=0) # sum of each column
array([12, 15, 18, 21])
b.min(axis=1) # min of each row
array([)
汎用関数
NumPy は sin、cos、exp などの馴染みのある数学関数を提供します。NumPy では、これらは「ユニバーサル関数」と呼ばれます ( ufunc)。NumPy では、これらの関数は配列の要素ごとに動作し、配列を出力します。
B = np.arange(3)
B
array([0, 1, 2])
np.exp(B)
array([1. , 2.71828183, 7.3890561 ])
np.sqrt(B)
array([0. , 1. , 1.41421356])
C = np.array([2., -1., 4.])
np.add(B, C)
array([2., 0., 6.])
インデックス付け、スライス、反復処理
一次元配列は、リスト やその他のPythonシーケンスと同様に、インデックス指定、スライス、反復処理が可能です 。
a = np.arange(10)**3
a
array([ 0, 1, 8, 27, 64, 125, 216, 343, 512, 729])
a[2]
8
a[2:5]
array([ 8, 27, 64])
# equivalent to a[0:6:2] = 1000;
# from start to position 6, exclusive, set every 2nd element to 1000
a[:6:2] = 1000
a
array([1000, 1, 1000, 27, 1000, 125, 216, 343, 512, 729])
a[::-1] # reversed a
array([ 729, 512, 343, 216, 125, 1000, 27, 1000, 1, 1000])
for i in a:
print(i**(1 / 3.))
9.999999999999998 # may vary
1.0
9.999999999999998
3.0
9.999999999999998
4.999999999999999
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998
多次元配列は、軸ごとに1つのインデックスを持つことができます。これらのインデックスは、カンマで区切られたタプルで指定します。
def f(x, y):
return 10 * x + y
b = np.fromfunction(f, (5, 4), dtype=int)
b
array(0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23],
[30, 31, 32, 33],
[40, 41, 42, 431:3, :] # each column in the second and third row of b
array(10, 11, 12, 13],
[20, 21, 22, 23)
b[2, 3]
23
b[0:5, 1] # each row in the second column of b
array([ 1, 11, 21, 31, 41])
b[:, 1] # equivalent to the previous example
array([ 1, 11, 21, 31, 41])
b[)
軸の数よりも少ないインデックスが指定されている場合、欠落しているインデックスは完全なスライスとみなされます。:
b[-1] # the last row. Equivalent to b[-1, :]
array([40, 41, 42, 43])
括弧内の式はb[i]、 として扱われ、残りの軸を表すために必要なi 数の が続きます:。NumPy では、ドットを使用して として記述することもできます 。b[i, ...]
ドット( )は...、完全なインデックスタプルを生成するために必要な数のコロンを表します。たとえば、xが 5 つの軸を持つ配列の場合、
-
x[1, 2, ...]は、x[1, 2, :, :, :] -
x[..., 3]〜へそしてx[:, :, :, :, 3] -
x[4, ..., 5, :]に。x[4, :, :, 5, :]
c = np.array([ 0, 1, 2], # a 3D array (two stacked 2D arrays)
[ 10, 12, 13,
100, 101, 102],
[110, 112, 1131]
array(100, 101, 102],
[110, 112, 113:, :, 2]
array(2, 13],
[102, 113])
c.shape
(2, 2, 3)
c[1, ...] # same as c[1, :, :] or c[)
c[..., 2] # same as c[)
多次元配列の反復処理は、最初の軸に関して行われます。
for row in b:
print(row)
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
ただし、配列の各要素に対して操作を実行したい場合は、 配列のすべての要素を反復処理するflat属性 を使用できます。
for element in b.flat:
print(element)
0
1
2
3
10
11
12
13
20
21
22
23
30
31
32
33
40
41
42
43
形状操作
配列の形状を変更する
配列の形状は、各軸に沿った要素の数によって決まります。
a = np.floor(10 * rg.random((3, 4)))
a
array(3., 7., 3., 4.],
[1., 4., 2., 2.],
[7., 2., 4., 9.)
a.shape
(3, 4)
配列の形状は、さまざまなコマンドで変更できます。以下の3つのコマンドはすべて変更された配列を返しますが、元の配列は変更しないことに注意してください。
3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.])
a.reshape(6, 2) # returns the array with a modified shape
array(3., 7.],
[3., 4.],
[1., 4.],
[2., 2.],
[7., 2.],
[4., 9.)
a.T # returns the array, transposed
array(3., 1., 7.],
[7., 4., 2.],
[3., 2., 4.],
[4., 2., 9.a.ravel() # returns the array, flattened
array([)
a.T.shape
(4, 3)
a.shape
(3, 4)
から得られる配列の要素の順序はravel通常「Cスタイル」、つまり右端のインデックスが「最も速く変化する」ため、次の要素は です。配列が別の形状にリシェイプされた場合でも、配列は「Cスタイル」として扱われます。NumPy は通常この順序で格納される配列を作成するため、通常は引数をコピーする必要はありませんが、配列が別の配列のスライスを使用して作成された場合、または通常とは異なるオプションで作成された場合は、コピーが必要になる場合があります。関数 とは、オプションの引数を使用して、左端のインデックスが最も速く変化する FORTRAN スタイルの配列を使用するように指示することもできます。a[0, 0]a[0, 1]ravelravelreshape
このreshape関数は引数の形状を変更して返しますが、この ndarray.resizeメソッドは配列自体を変更します。
a
array(3., 7., 3., 4.],
[1., 4., 2., 2.],
[7., 2., 4., 9.)
a.resize((2, 6))
a
array(3., 7., 3., 4., 1., 4.],
[2., 2., 7., 2., 4., 9.)
-1形状変更操作のように寸法が指定された場合、他の寸法は自動的に計算されます。
異なる配列を積み重ねる
複数の配列を異なる軸に沿って積み重ねることができます。
a = np.floor(10 * rg.random((2, 2)))
a
array(9., 7.],
[5., 2.)
b = np.floor(10 * rg.random((2, 2)))
b
array(1., 9.],
[5., 1.)
np.vstack((a, b))
array(9., 7.],
[5., 2.],
[1., 9.],
[5., 1.)
np.hstack((a, b))
array(9., 7., 1., 9.],
[5., 2., 5., 1.)
この関数はcolumn_stack、1次元配列を列として2次元配列に積み重ねます。これは、hstack2次元配列の場合のみ、以下の関数と同等です。
from numpy import newaxis
np.column_stack((a, b)) # with 2D arrays
array(9., 7., 1., 9.],
[5., 2., 5., 1.3., 8.])
np.column_stack((a, b)) # returns a 2D array
array(4., 3.],
[2., 8.:, newaxis] # view `a` as a 2D column vector
array(4.],
[2.:, newaxis]))
array(4., 3.],
[2., 8.:, newaxis])) # the result is the same
array(4., 3.],
[2., 8.)
a = np.array([4., 2.])
b = np.array([)
np.hstack((a, b)) # the result is different
array([4., 2., 3., 8.])
a[)
np.column_stack((a[:, newaxis], b[)
np.hstack((a[:, newaxis], b[)
一般的に、2 次元を超える配列の場合、 hstack第 2 軸に沿ってスタックし、vstack第 1 軸に沿ってスタックし、concatenate 連結を行う軸の番号を指定するオプションの引数を許可します。
注記
複雑なケースでは、r_数値c_を1つの軸に沿って積み重ねて配列を作成するのに役立ちます。範囲リテラルの使用が可能になります:。
np.r_[1:4, 0, 4]
array([1, 2, 3, 0, 4])
配列を引数として使用する場合、 r_およびは デフォルトの動作においておよびと c_似ています が、連結する軸の番号を指定するオプションの引数を許可します。vstackhstack
1つの配列を複数の小さな配列に分割する
を使用するとhsplit、配列を水平軸に沿って分割できます。分割するには、同じ形状の配列の数を指定するか、分割を行う列を指定します。
a = np.floor(10 * rg.random((2, 12)))
a
array(6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.],
[8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.array(6., 7., 6., 9.],
[8., 5., 5., 7.), array(0., 5., 4., 0.],
[1., 8., 6., 7.), array(6., 8., 5., 2.],
[1., 8., 1., 0.array(6., 7., 6.],
[8., 5., 5.), array(9.],
[7.), array(0., 5., 4., 0., 6., 8., 5., 2.],
[1., 8., 6., 7., 1., 8., 1., 0.)
# Split `a` into 3
np.hsplit(a, 3)
[)]
# Split `a` after the third and the fourth column
np.hsplit(a, (3, 4))
[)]
vsplit垂直軸に沿って分割し、array_splitどの軸に沿って分割するかを指定できます。
コピー数と閲覧数
配列を操作・解析する際、データが新しい配列にコピーされる場合とされない場合があります。これは初心者にとって混乱の原因となることがよくあります。主なケースは次の3つです。
コピーなし
単純な代入では、オブジェクトやそのデータのコピーは作成されません。
Pythonは可変オブジェクトを参照として渡すため、関数呼び出しではコピーは作成されません。
def f(x):
print(id(x))
id(a) # id is a unique identifier of an object
148293216 # may vary
f(a)
148293216 # may vary
表示またはシャローコピー
異なる配列オブジェクトが同じデータを共有できます。このviewメソッドは、同じデータを参照する新しい配列オブジェクトを作成します。
0, 4] = 1234 # a's data changes
a
array(0, 1, 2, 3],
[1234, 5, 6, 7],
[ 8, 9, 10, 11c = a.view()
c is a
False
c.base is a # c is a view of the data owned by a
True
c.flags.owndata
False
c = c.reshape((2, 6)) # a's shape doesn't change, reassigned c is still a view of a
a.shape
(3, 4)
c[)
配列をスライスすると、その配列のビューが返されます。
:] = 10
a
array(0, 10, 10, 3],
[1234, 10, 10, 7],
[ 8, 10, 10, 11s = a[:, 1:3]
s[:] = 10 # s[:] is a view of s. Note the difference between s = 10 and s[)
ディープコピー
このcopyメソッドは、配列とそのデータの完全なコピーを作成します。
0, 0] = 9999
a
array(0, 10, 10, 3],
[1234, 10, 10, 7],
[ 8, 10, 10, 11d = a.copy() # a new array object with new data is created
d is a
False
d.base is a # d doesn't share anything with a
False
d[)
copy元の配列が不要になった場合は、スライス後に呼び出す必要がある場合があります。たとえば、がa巨大な中間結果であり、最終結果にbは のごく一部しか含まれていない場合、スライスを使用してaを構築する際には、ディープコピーを作成する必要がありますb。
a = np.arange(int(1e8))
b = a[:100].copy()
del a # the memory of ``a`` can be released.
が代わりに使用される場合、はによって参照され、が実行されてもメモリ内に保持されます。b = a[:100]abdel a
「コピーと閲覧」も参照してください。
関数とメソッドの概要
以下は、NumPyの便利な関数とメソッド名をカテゴリ別にまとめたリストです。完全なリストについては、「トピック別のルーチンとオブジェクト」を参照してください。
- 配列の作成
-
arange、、、、、、、、、、、、、、、、、、、、、arraycopyemptyempty_likeeyefromfilefromfunctionidentitylinspacelogspacemgridogridonesones_liker_zeroszeros_like - 変換
-
ndarray.astype、、、、 マットatleast_1datleast_2datleast_3d - 操作
-
array_split、、、、、、、、、、、、、、、、、、、、、、、column_stackconcatenatediagonaldsplitdstackhsplithstackndarray.itemnewaxisravelrepeatreshaperesizesqueezeswapaxestaketransposevsplitvstack - 質問
- 注文
- 業務
-
choose、、、、、、、、、、、、、、compresscumprodcumsuminnerndarray.fillimagprodputputmaskrealsum - 基本統計
- 基本的な線形代数
-
cross、、、、dotouterlinalg.svdvdot
あまり基本的ではない
放送規則
ブロードキャスト機能により、汎用関数は、形状が完全に一致しない入力に対しても、意味のある方法で処理できるようになる。
ブロードキャストの最初のルールは、すべての入力配列の次元数が同じでない場合、すべての配列の次元数が同じになるまで、小さい配列の形状の先頭に「1」が繰り返し追加されるというものです。
ブロードキャストの2つ目のルールは、特定の次元でサイズが1である配列は、その次元で最大の形状を持つ配列のサイズを持つかのように動作することを保証します。「ブロードキャスト」配列では、配列要素の値は、その次元で同じであると想定されます。
ブロードキャストルールを適用した後、すべての配列のサイズが一致する必要があります。詳細については、「ブロードキャスト」を参照してください。
高度なインデックス作成とインデックスのトリック
NumPy は通常の Python シーケンスよりも多くのインデックス機能を提供します。整数とスライスによるインデックスに加えて、前述のように、配列は整数の配列とブール値の配列でインデックス付けできます。
インデックスの配列によるインデックス付け
1, 1, 9, 64, 25])
j = np.array(3, 4], [9, 7j] # the same shape as `j`
array(9, 16],
[81, 49a = np.arange(12)**2 # the first 12 square numbers
i = np.array([1, 1, 3, 8, 5]) # an array of indices
a[i] # the elements of `a` at the positions `i`
array([) # a bidimensional array of indices
a[)
インデックス付き配列aが多次元の場合、単一のインデックス配列は の最初の次元を参照しますa。次の例では、パレットを使用してラベルの画像をカラー画像に変換することで、この動作を示しています。
palette = np.array(0, 0, 0], # black
[255, 0, 0], # red
[0, 255, 0], # green
[0, 0, 255], # blue
[255, 255, 255) # white
image = np.array(0, 1, 2, 0], # each value corresponds to a color in the palette
[0, 3, 4, 0image] # the (2, 4, 3) color image
array([ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0,
0, 0, 0],
[ 0, 0, 255],
[255, 255, 255],
[ 0, 0, 0)
palette[])
複数の次元にインデックスを指定することもできます。各次元のインデックスの配列は同じ形状でなければなりません。
a = np.arange(12).reshape(3, 4)
a
array(0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11)
i = np.array(0, 1], # indices for the first dim of `a`
[1, 2)
j = np.array(2, 1], # indices for the second dim
[3, 3i, j] # i and j must have equal shape
array(2, 5],
[ 7, 11i, 2]
array(2, 6],
[ 6, 10:, j]
array([ 2, 1],
[ 3, 3,
6, 5],
[ 7, 7,
10, 9],
[11, 11)
a[)
a[)
a[])
Python では、は とまったく同じなので、 にとを入れて、それを使ってインデックス付けを行うことができます。arr[i, j]arr[(i, j)]ijtuple
iただし、と を配列に入れてこれを行うことはできませんj。この配列は の最初の次元のインデックスとして解釈されるためですa。
tuple(s)]
array(2, 5],
[ 7, 11s = np.array([i, j])
# not what we want
a[s]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index 3 is out of bounds for axis 0 with size 3
# same as `a[i, j]`
a[)
配列によるインデックスのもう 1 つの一般的な用途は、時間依存の系列の最大値の検索です。
20. , 51.25, 82.5 , 113.75, 145. ])
data
array(0. , 0.84147098, 0.90929743, 0.14112001],
[-0.7568025 , -0.95892427, -0.2794155 , 0.6569866 ],
[ 0.98935825, 0.41211849, -0.54402111, -0.99999021],
[-0.53657292, 0.42016704, 0.99060736, 0.65028784],
[-0.28790332, -0.96139749, -0.75098725, 0.14987721time = np.linspace(20, 145, 5) # time scale
data = np.sin(np.arange(20)).reshape(5, 4) # 4 time-dependent series
time
array([)
# index of the maxima for each series
ind = data.argmax(axis=0)
ind
array([2, 0, 3, 1])
# times corresponding to the maxima
time_max = time[ind]
data_max = data[ind, range(data.shape[1])] # => data[ind[0], 0], data[ind[1], 1]...
time_max
array([ 82.5 , 20. , 113.75, 51.25])
data_max
array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
np.all(data_max == data.max(axis=0))
True
割り当てるターゲットとして配列のインデックスを使用することもできます。
ただし、インデックスのリストに繰り返しが含まれている場合、割り当ては複数回実行され、最後の値が残されます。
これは十分に合理的ですが、Python の構文を使用する場合は +=、期待どおりに動作しない可能性があるため注意してください。
インデックスのリストに 0 が2回出現するにもかかわらず、0番目の要素は1回だけインクリメントされます。これは、Pythonではが と同等であることが求められるためです。a += 1a = a + 1
ブール配列によるインデックス付け
整数インデックスの配列で配列をインデックス付けする場合、選択するインデックスのリストを提供します。ブールインデックスの場合はアプローチが異なり、配列内の必要な項目と不要な項目を明示的に選択します。
ブールインデックスの最も自然な方法は、元の配列と同じ形状のブール配列を使用することです。
a = np.arange(12).reshape(3, 4)
b = a > 4
b # `b` is a boolean with `a`'s shape
array(False, False, False, False],
[False, True, True, True],
[ True, True, True, True)
a[b] # 1d array with the selected elements
array([ 5, 6, 7, 8, 9, 10, 11])
このプロパティは割り当てにおいて非常に役立ちます:
ブールインデックスを使用してマンデルブロ集合のイメージを生成する方法については、次の例をご覧ください。
import numpy as np
import matplotlib.pyplot as plt
def mandelbrot(h, w, maxit=20, r=2):
"""Returns an image of the Mandelbrot fractal of size (h,w)."""
x = np.linspace(-2.5, 1.5, 4*h+1)
y = np.linspace(-1.5, 1.5, 3*w+1)
A, B = np.meshgrid(x, y)
C = A + B*1j
z = np.zeros_like(C)
divtime = maxit + np.zeros(z.shape, dtype=int)
for i in range(maxit):
z = z**2 + C
diverge = abs(z) > r # who is diverging
div_now = diverge & (divtime == maxit) # who is diverging now
divtime[div_now] = i # note when
z[diverge] = r # avoid diverging too much
return divtime
plt.clf()
plt.imshow(mandelbrot(400, 400))

ブール値でインデックスを付ける 2 番目の方法は、整数インデックスに似ています。配列の各次元に対して、必要なスライスを選択する 1D ブール配列を指定します。
b1, :] # selecting rows
array(4, 5, 6, 7],
[ 8, 9, 10, 11b1] # same thing
array(4, 5, 6, 7],
[ 8, 9, 10, 11:, b2] # selecting columns
array(0, 2],
[ 4, 6],
[ 8, 10a = np.arange(12).reshape(3, 4)
b1 = np.array([False, True, True]) # first dim selection
b2 = np.array([True, False, True, False]) # second dim selection
a[)
a[)
a[)
a[b1, b2] # a weird thing to do
array([ 4, 10])
1次元ブール配列の長さは、スライスする次元(または軸)の長さと一致する必要があることに注意してください。前の例では、 の長さは3(の行b1数)で、 (長さ4)は の2番目の軸(列)のインデックスに適しています 。ab2a
ix_() 関数
このix_関数は、異なるベクトルを結合して、各n組の結果を得るために使用できます。例えば、ベクトルa、b、cのそれぞれから得られたすべての3組について、a+b*cを計算したい場合、次のように記述します。
5, 4, 6, 8, 3])
ax, bx, cx = np.ix_(a, b, c)
ax
array([2,
3,
4,
5])
bx
array([8],
[5],
[4])
cx
array([5, 4, 6, 8, 3])
ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
result = ax + bx * cx
result
array([42, 34, 50, 66, 26],
[27, 22, 32, 42, 17],
[22, 18, 26, 34, 14,
43, 35, 51, 67, 27],
[28, 23, 33, 43, 18],
[23, 19, 27, 35, 15,
44, 36, 52, 68, 28],
[29, 24, 34, 44, 19],
[24, 20, 28, 36, 16,
45, 37, 53, 69, 29],
[30, 25, 35, 45, 20],
[25, 21, 29, 37, 17a = np.array([2, 3, 4, 5])
b = np.array([8, 5, 4])
c = np.array([])
result[3, 2, 4]
17
a[3] + b[2] * c[4]
17
次のようにして reduce を実装することもできます。
def ufunc_reduce(ufct, *vectors):
vs = np.ix_(*vectors)
r = ufct.identity
for v in vs:
r = ufct(r, v)
return r
そして次のように使用します。
ufunc_reduce(np.add, a, b, c)
array([15, 14, 16, 18, 13],
[12, 11, 13, 15, 10],
[11, 10, 12, 14, 9,
16, 15, 17, 19, 14],
[13, 12, 14, 16, 11],
[12, 11, 13, 15, 10,
17, 16, 18, 20, 15],
[14, 13, 15, 17, 12],
[13, 12, 14, 16, 11,
18, 17, 19, 21, 16],
[15, 14, 16, 18, 13],
[14, 13, 15, 17, 12])
通常の ufunc.reduce と比較したこのバージョンの reduce の利点は、出力のサイズとベクトルの数を掛け合わせた引数配列の作成を回避するためにブロードキャスト ルールを使用することです 。
文字列によるインデックス
構造化配列を参照してください。
コツとヒント
ここでは、短くて役立つヒントのリストを示します。
「自動」再形成
配列の次元を変更するには、サイズの 1 つを省略すると、自動的に推測されます。
a = np.arange(30)
b = a.reshape((2, -1, 3)) # -1 means "whatever is needed"
b.shape
(2, 5, 3)
b
array([ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14,
15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29])
ベクタースタッキング
同じサイズの行ベクトルのリストから2次元配列を構築するにはどうすればよいでしょうか?MATLABではこれは非常に簡単です。2つのベクトルが同じ長さであれば、 を実行するだけで済みますx。NumPyでは、スタッキングを行う次元に応じて、関数、、を使用します。例えば、ym=[x;y]column_stackdstackhstackvstack
x, y])
m
array(0, 2, 4, 6, 8],
[0, 1, 2, 3, 4x = np.arange(0, 10, 2)
y = np.arange(5)
m = np.vstack([)
xy = np.hstack([x, y])
xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4])
2 次元を超える関数の背後にあるロジックは奇妙になる可能性があります。
ヒストグラム
NumPyhistogram関数を配列に適用すると、配列のヒストグラムとビンのエッジのベクトルという2つのベクトルが返されます。注意: matplotlibにもヒストグラムを作成する関数(histMatlabでは と呼ばれます)がありますが、これはNumPyのものとは異なります。主な違いは、 はpylab.histヒストグラムを自動的にプロットするのに対し、 numpy.histogramはデータのみを生成する点です。
import numpy as np
rg = np.random.default_rng(1)
import matplotlib.pyplot as plt
# Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
mu, sigma = 2, 0.5
v = rg.normal(mu, sigma, 10000)
# Plot a normalized histogram with 50 bins
plt.hist(v, bins=50, density=True) # matplotlib version (plot)
(array...)
# Compute the histogram with numpy and then plot it
(n, bins) = np.histogram(v, bins=50, density=True) # NumPy version (no plot)
plt.plot(.5 * (bins[1:] + bins[:-1]), n)

Matplotlib >=3.4 では、 も使用できます。plt.stairs(n, bins)
さらに読む
-
Pythonチュートリアル
-
matlab 、R、IDL、NumPy/SciPyの辞書

コメント
最新を表示する
NG表示方式
NGID一覧