Yamamoto's Laboratory
多次元配列
ファイル

NumPy多次元配列 (ndarray)

ここでは,Python の NumPy の多次元配列 (ndarray) について説明します.これは Numpy の基本的なデータ保持形式なので,ndarray の理解を避けては NumPy を使いこなせません.以下が,本ページの内容です.

目次


多次元配列「ndarray」とは

特徴

ndarray は Numpy で使われる多次元配列です.これは一般的なコンパイラー言語,例えば C++ の配列(もちろん多次元)と似たところがあります.ndarray の特徴は,次のとおりです.

  • 配列の要素のアクセスには整数のインデックスを使う.
  • 全ての要素のデータの型は同一である (要素毎のメモリーサイズが同一).
  • データは,メモリーの連続した領域に格納される.

このようにすることで,データに高速にアクセスすることができます.大規模なデータを取り扱うことが多い数値計算では,「データへの高速アクセス」は極めて重要です.

一方,元々 Python に備わっているリストでは,要素のデータの型は同一である必要はありません.型を気にせずにプログラムを書くことができる反面,データへの高速アクセスができなくなります.データの型が異なれば,メモリサーズが異なるためです.したがって,メモリーの連続した領域へのデータの格納ができなくなります (可能かもしれないが難しい).すると,要素へのアクセスに時間がかかるようになり,高速の演算には不向きなデータの保持方法と言えます.

具体例

以下に具体例を示します.非常に単純な例なので,およその動作は想像できると思います.003 – 014 行で三次元の配列を作成します.リストを numpy.array() で ndarray の配列オブジェクトに変換します.3×3×3 の配列です.016 で出来上がったオブジェクトのクラスを確認します.このオブジェクは,<numpy.ndarray>です.017行で配列の次元,018行で構造を表示します.019 – 021 行で配列の要素を表示します.結果を見れば,理解できるでしょう.

ndarray の具体例 実行結果
001   import numpy as np
002   
003   a = np.array([[\
004                  [  0,  1,   2],\
005                  [ 10,  11, 12],\
006                  [ 20,  31, 32]],\
007                 [\
008                  [100, 101, 102],\
009                  [110, 111, 112],\
010                  [120, 121, 122]],\
011                 [\
012                  [200, 201, 202],\
013                  [210, 211, 212],\
014                  [220, 221, 222]]])
015   
016   print('type:  ',type(a))
017   print('dim:   ', a.ndim)
018   print('shape: ', a.shape)
019   print('a[1]:       ', a[1])
020   print('a[1][2]:    ', a[1][2])
021   print('a[1][2][0]: ', a[1][2][0])
type:   <class 'numpy.ndarray'>
dim:    3
shape:  (3, 3, 3)
a[1]:        [[100 101 102]
 [110 111 112]
 [120 121 122]]
a[1][2]:     [120 121 122]
a[1][2][0]:  120

軸の概念

多次元配列「ndarray」は,通常のプログラミング言語の配列と考えることもできます.違いは,ndarray にはとても便利な機能が沢山あることです.その便利な機能を使うためには軸(axis)という概念を理解する必要があります.

例えば4次元配列 arr[i][j][k][l] を考えます.ここで,軸:axis=0 は最初の軸 [i] を,軸:axis=1 は [j] を,軸:axis=2 は [j] を,軸:axis=3 は [j] を表します.軸を表す整数は,配列の添字の序数を表しているでけです.

例えば,ndarray のメソッド ope() があるとします.そして,これは配列 arr に作用します.しばしば,配列に作用するメソッドは,arr.ope(axis=2)というような書き方許されます.これは配列にメソッド ope が作用した結果を返します.具体的には,res=arr.ope(axis=2)というような感じです.このように記述すると,メソッド ope() は,軸:axis=2 (三番目の[k]) を値を変えた値を引数(複数)に作用します.式で書くと以下のような感じです.

\begin{align} res[i][j][l]=ope(arr[i][j][0][l],\,arr[i][j][1][l],\,arr[i][j][2][l],\,\cdots) \end{align}

理解を深めるために,もうちょっと具体的な例を示します.以下のプログラムは,軸:axis=1 に沿って,配列の和

\begin{align} a[i][k]=\sum_j a[i][j][k] \end{align}

を計算します.プログラムでは,018 行の「res = a.sum(axis=1)」です.以下のプログラムで確認できます.

ndarray の軸を示す例 実行結果
001   import numpy as np
002   
003   a = np.array([[\
004                  [  0,  1,   2],\
005                  [ 10,  11, 12],\
006                  [ 20,  31, 32]],\
007                 [\
008                  [100, 101, 102],\
009                  [110, 111, 112],\
010                  [120, 121, 122]],\
011                 [\
012                  [200, 201, 202],\
013                  [210, 211, 212],\
014                  [220, 221, 222]]])
015   
016   
017   # --- res[i][j] = sum_k a[i][k][j] ---
018   res = a.sum(axis=1)
019   print(res, '\n')
020   
021   print(a[0][0][0]+a[0][1][0]+a[0][2][0])  # res[0][0]
022   print(a[0][0][1]+a[0][1][1]+a[0][2][1])  # res[0][1]
023   print(a[0][0][2]+a[0][1][2]+a[0][2][2])  # res[0][2]
024   print(a[1][0][0]+a[1][1][0]+a[1][2][0])  # res[1][0]
025   print(a[1][0][1]+a[1][1][1]+a[1][2][1])  # res[1][1]
026   print(a[1][0][2]+a[1][1][2]+a[1][2][2])  # res[1][2]
027   print(a[2][0][0]+a[2][1][0]+a[2][2][0])  # res[2][0]
028   print(a[2][0][1]+a[2][1][1]+a[2][2][1])  # res[2][1]
029   print(a[2][0][2]+a[2][1][2]+a[2][2][2])  # res[2][2]
[[ 30  43  46]
 [330 333 336]
 [630 633 636]] 

30
43
46
330
333
336
630
633
636

多次元配列の生成

配列作成ルーチン

NumPy には,いくつかの配列作成の関数が用意されています.詳細は,「Array creation routines」に記載されています.これらは配列作成に便利です.

値がゼロ or 1

Python Numpy の配列生成メソッド
メソッド 動作
empty(shape[, dtype, order]) 初期化無し(値不定)で,配列を生成します.[詳しい説明と具体例]
empty_like(a[, dtype, order, subok]) 既存の配列と同じシェイプ・型で,初期化なしで配列を生成します.[詳しい説明と具体例]
eye(N[, M, k, dtype, order]) 正方行列でない単位行列を生成します.対角成分以外も 1 にできます.[詳しい説明と具体例]
identity(n[, dtype]) 正方行列の単位行列を生成します.[詳しい説明と具体例]
ones(shape[, dtype, order]) すべての要素の値が 1 の配列を生成します.[詳しい説明と具体例]
ones_like(a[, dtype, order, subok]) 既存の配列と同じシェイプ・型で,要素の値が 1 の配列を生成します.[詳しい説明と具体例]
zeros(shape[, dtype, order]) すべての要素の値が 0 の配列を生成します.[詳しい説明と具体例]
zeros_like(a[, dtype, order, subok]) 既存の配列と同じシェイプ・型で,要素の値が 0 の配列を生成します.[詳しい説明と具体例]
full(shape, fill_value[, dtype, order]) すべての要素の値が同一の配列を生成します.要素の値は任意に指定できます.[詳しい説明と具体例]
full_like(a, fill_value[, dtype, order, subok]) 既存の配列と同じシェイプ・型で,すべての要素の値が同一の配列を生成します.要素の値は任意に指定できます.[詳しい説明と具体例]

既存のデータから

Python Numpy の配列を既存のデータから生成
メソッド 動作
array(object[, dtype, copy, order, subok, ndmin]) 配列のようなオブジェクト (リストやタプルなど) から配列を作成.[詳しい説明と具体例]
asarray(a[, dtype, order]) 配列へ変換します.元の配列が numpy.ndarray の場合は,同じ id になる.[詳しい説明と具体例]
asanyarray(a[, dtype, order]) Convert the input to an ndarray, but pass ndarray subclasses through.
ascontiguousarray(a[, dtype]) Return a contiguous array in memory (C order).
asmatrix(data[, dtype]) Interpret the input as a matrix.
copy(a[, order]) Return an array copy of the given object.
frombuffer(buffer[, dtype, count, offset]) Interpret a buffer as a 1-dimensional array.
fromfile(file[, dtype, count, sep]) Construct an array from data in a text or binary file.
fromfunction(function, shape, **kwargs) Construct an array by executing a function over each coordinate.
fromiter(iterable, dtype[, count]) Create a new 1-dimensional array from an iterable object.
fromstring(string[, dtype, count, sep]) A new 1-D array initialized from text data in a string.
loadtxt(fname[, dtype, comments, delimiter, …]) Load data from a text file.

record arrays

Python Numpy の配列をから
メソッド 動作
core.records.array(obj[, dtype, shape, …]) Construct a record array from a wide-variety of objects.
core.records.fromarrays(arrayList[, dtype, …]) create a record array from a (flat) list of arrays
core.records.fromrecords(recList[, dtype, …]) create a recarray from a list of records in text form
core.records.fromstring(datastring[, dtype, …]) create a (read-only) record array from binary data contained in
core.records.fromfile(fd[, dtype, shape, …]) Create an array from binary file data

character arrays

Python Numpy の配列をから
メソッド 動作
core.defchararray.array(obj[, itemsize, …]) Create a chararray.
core.defchararray.asarray(obj[, itemsize, …]) Convert the input to a chararray, copying the data only if necessary.

Numerical ranges

Python Numpy の配列をから
メソッド 動作
arange([start,] stop[, step,][, dtype]) Return evenly spaced values within a given interval.
linspace(start, stop[, num, endpoint, …]) Return evenly spaced numbers over a specified interval.
logspace(start, stop[, num, endpoint, base, …]) Return numbers spaced evenly on a log scale.
geomspace(start, stop[, num, endpoint, dtype]) Return numbers spaced evenly on a log scale (a geometric progression).
meshgrid(*xi, **kwargs Return coordinate matrices from coordinate vectors.
mgrid nd_grid instance which returns a dense multi-dimensional “meshgrid”.
ogrid 開いた多次元「meshgrid」を返す nd_grid インスタンス[詳しい説明と具体例].

Building matrices

Python Numpy の配列をから
メソッド 動作
diag(v[, k]) Extract a diagonal or construct a diagonal array.
diagflat(v[, k]) Create a two-dimensional array with the flattened input as a diagonal.
tri(N[, M, k, dtype]) An array with ones at and below the given diagonal and zeros elsewhere.
tril(m[, k]) Lower triangle of an array.
triu(m[, k]) Upper triangle of an array.
vander(x[, N, increasing]) Generate a Vandermonde matrix.

The Matrix class

Python Numpy の配列をから
メソッド 動作
mat(data[, dtype]) Interpret the input as a matrix.
bmat(obj[, ldict, gdict]) Build a matrix object from a string, nested sequence, or array.

リストを使う方法

リストを変換

numpy の多次元配列は,Python に備わっているリストを使って作成することができます.リストを np.array(リスト) とすると,多次元配列になります(具体例).

arr = np.array(リスト)         # arrという配列を作成

リスト内包表記を使う

リスト内包表記を使うと,かなり複雑なリストの作成が可能です.そのリストを配列に変換します.

一次元

一次元の配列の作成は,次のようにします(具体例).

arr = np.array([ for 変数 in リスト])      # arrという配列を作成
多次元

多次元の配列の作成は,次のようにします(具体例).

arr = np.array([[[ for 変数 in リスト] 変数 in リスト] 変数 in リスト])

空配列の生成と値の追加

空の配列を作ると便利なことがあります.特に最初に空の配列を作り,値を追加することがあります.空の配列は,空のリスト ([]) を作り,nd.array() で多次元配列 (ndarray) に変換します(具体例).

arr = np.array([])            # arrという空の配列を作成
arr = np.append(arr, 3.14)    # arr に 3.14 を追加

値を指定

ゼロ埋め

要素がゼロで埋められた配列は,各軸の要素数が書かれたタプルを引数とした「np.zero(要素数のタプル)」を使います.

np.zero()でゼロ埋め配列 実行結果
import numpy as np

a = np.zeros((2, 4, 6))

print(a)

[[[ 0.  0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.  0.]]

 [[ 0.  0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.  0.]
  [ 0.  0.  0.  0.  0.  0.]]]

連続した値の設定

要素が連続した値をとる配列は,「numpy.arange(x0, x1, dx).reshape(n1, n2, n3, …)」とします.x0 は初期値,x1 は端の値, dx は増分です.「numpy.arange(x0, x1, dx)」で連続した一次元の配列を生成します.x1 以下の値,x1は生成されません.そして,reshape()を使うことにより,多次元にできます(具体例).

arr_1D = np.arange(x0, x1, dx)
arr_2D = np.arange(x0, x1, dx).reshape(n1, n2, n3, )

ファイルからの読み込み

genfromtxt() を使って,ファイルから配列 (二次元) の値を読み込むことができます.詳細は「ファイル: 読み込みgenfromtxt を使った読み込み」を参照下さい,

要素の抽出(スライシング)

配列の一部を取り出すことをスライシング,あるいはインデキシングと言います.

インデックスによる指定

固定で指定

インデックスを指定することにより,配列の要素を取り出すことができます.具体例を以下に示します.これらの動作は説明するまでも無いですね.配列名を書けば全てが選択されます.軸 (配列のインデックス) の選択もできます.

インデックスによる配列の要素抽出 実行結果
import numpy as np

ary = np.arange(0,1000,1).reshape(10,10,10)[0:3, 0:3, 0:3]

print("-- ary ---")
print(ary)

print("\n-- ary[2] --")
print(ary[2])

print("\n-- ary[2][1] --")
print(ary[2][1])

print("\n-- ary[2][1][0] --")
print(ary[2][1][0])
-- ary -----------
[[[  0   1   2]
  [ 10  11  12]
  [ 20  21  22]]

 [[100 101 102]
  [110 111 112]
  [120 121 122]]

 [[200 201 202]
  [210 211 212]
  [220 221 222]]]

-- ary[2] --------
[[200 201 202]
 [210 211 212]
 [220 221 222]]

-- ary[2][1] -----
[210 211 212]

-- ary[2][1][0] --
210

範囲で指定

先の例では,任意の第二軸でスライスした配列を取得できません.そのような場合,より一般的な 配列[軸1指定, 軸2指定,軸3指定, …]を使います.軸指定には,番号指定(例 [2]),範囲指定(例 [3:7]),全て指定([:])があります.範囲指定を [3:7] とすると,インデックス[3, 4, 5, 6]の指定になります.以下,具体例を示します.

インデックス(範囲指定)による配列の要素抽出 実行結果
import numpy as np

ary = np.arange(0,1000,1).reshape(10,10,10)[0:4, 0:4, 0:4]

print("\n-- ary[1:3] --")
print(ary[1:3]) 

print("\n-- ary[:,1] --")
print(ary[:, 1])

print("\n-- ary[:,:,2] --")
print(ary[:,:,2])

print("\n-- ary[1:3, 0:2, 1:3] --")
print(ary[1:3, 0:2, 1:3])
-- ary[1:3] --
[[[100 101 102 103]
  [110 111 112 113]
  [120 121 122 123]
  [130 131 132 133]]

 [[200 201 202 203]
  [210 211 212 213]
  [220 221 222 223]
  [230 231 232 233]]]

-- ary[:,1] --
[[ 10  11  12  13]
 [110 111 112 113]
 [210 211 212 213]
 [310 311 312 313]]

-- ary[:,:,2] --
[[  2  12  22  32]
 [102 112 122 132]
 [202 212 222 232]
 [302 312 322 332]]

-- ary[1:3, 0:2, 1:3] --
[[[101 102]
  [111 112]]

 [[201 202]
  [211 212]]]

配列の変形

インデックス(軸)の交換

transopse()

transpose() を使うと任意の軸を簡単に入れ替えられます.配列のインデックスは軸を表します.例えば三次元配列 ary[ix][iy][iz] は,3つの軸 (ix, iy, iz) を持ちます.メソッド transpose() では,それぞれの軸に整数 (0, 1, 2) が割り振られています.(ix=0, iy=1, iz=2) のようにです.もちろん,4, 5, …, 次元でも同じです.軸を入れ替えて ary[iy][iz][ix] とするには,ary.transpose(1, 2, 0)とします.より複雑な四次元配列を使った例を以下に示します.

numpy.transpose()の例 実行結果
import numpy as np

#----- 四次元配列 ---------
a = np.arange(0,10000,1).reshape(10, 10, 10, 10)

#----- b[k][i][l][j] = a[i][j][k][l] -----
b = a.transpose(2,0,3,1)

print('a = ', a[9][7][1][3])
print('b = ', b[1][9][3][7])
a =  9713
b =  9713

引数無しで transpose() を使うと,配列のインデックスの並びが逆順になります.それは,以下の例で確認できます.

numpy.transpose(引数なし)の例 実行結果
import numpy as np

#----- 5次元配列 ---------
a = np.arange(0,100000,1).reshape(10, 10, 10, 10, 10)

#----- b[m][l][k][j][i] = a[i][j][k][l][m] -----
b = a.transpose()

print('a = ', a[8][7][6][5][4])
print('b = ', b[4][5][6][7][8])
a =  87654
b =  87654

二次元に配列の場合,引数なしの transpose() は理にかなった名前です.結果は,転置行列になります.

swapaxes()

軸の入れ替えを行うメソッドには,transpose() の他に swapaxes() があります.この swapaxes() は指定した二つの軸の入れ替えを行います.transpose() のように,一度に複数の軸の入れ替えはできません.メソッド名のとおりですね.

numpy.swapaxes()の例 実行結果
import numpy as np

#----- 四次元配列 ---------
a = np.arange(0,10000,1).reshape(10, 10, 10, 10)

#----- b[i][k][j][l] = a[i][j][k][l] -----
b = a.swapaxes(1,2)

print('a = ', a[1][2][3][4])
print('b = ', b[1][3][2][4])
a =  1234
b =  1234

代入

配列の特定の要素の値の変更には,インデックスを指定します.例えば,「arr[3][6][2] = 3.14」のようにします.スカラーの場合は簡単です.配列の場合は,以下のようにします.[もっと詳しい具体例]

arr =np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1]],\
               [[1, 1, 1], [1, 1, 1], [1, 1, 1]]])
arr[0, 1, 2] = -9
arr[1][1][0:2] = [-12, -23]
arr[0, 0, 0:2] = [-99, -98]

メソッド

numpy.ndarray のメソッド
メソッド 動作
all([axis, out, keepdims]) 全てのエレメントが真の時に真を返す[具体例]
any([axis, out, keepdims]) エレメントのうち少なくともひとつが True の場合に,True を返す.
argmax([axis, out]) 最大要素のインデックスを返す.
argmin([axis, out]) Return indices of the minimum values along the given axis of a.
argpartition(kth[, axis, kind, order]) Returns the indices that would partition this array.
argsort([axis, kind, order]) Returns the indices that would sort this array.
astype(dtype[, order, casting, subok, copy]) Copy of the array, cast to a specified type.
byteswap([inplace]) Swap the bytes of the array elements
choose(choices[, out, mode]) Use an index array to construct a new array from a set of choices.
clip([min, max, out]) Return an array whose values are limited to [min, max].
compress(condition[, axis, out]) Return selected slices of this array along given axis.
conj() Complex-conjugate all elements.
conjugate() Return the complex conjugate, element-wise.
copy([order]) Return a copy of the array.
cumprod([axis, dtype, out]) Return the cumulative product of the elements along the given axis.
cumsum([axis, dtype, out]) Return the cumulative sum of the elements along the given axis.
diagonal([offset, axis1, axis2]) Return specified diagonals.
dot(b[, out]) Dot product of two arrays.
dump(file) Dump a pickle of the array to the specified file.
dumps() Returns the pickle of the array as a string.
fill(value) Fill the array with a scalar value.
flatten([order]) Return a copy of the array collapsed into one dimension.
getfield(dtype[, offset]) Returns a field of the given array as a certain type.
item(*args) Copy an element of an array to a standard Python scalar and return it.
itemset(*args) Insert scalar into an array (scalar is cast to array’s dtype, if possible)
max([axis, out, keepdims]) Return the maximum along a given axis.
mean([axis, dtype, out, keepdims]) Returns the average of the array elements along given axis.
min([axis, out, keepdims]) Return the minimum along a given axis.
newbyteorder([new_order]) Return the array with the same data viewed with a different byte order.
nonzero() Return the indices of the elements that are non-zero.
partition(kth[, axis, kind, order]) Rearranges the elements in the array in such a way that value of the element in kth position is in the position it would be in a sorted array.
prod([axis, dtype, out, keepdims]) Return the product of the array elements over the given axis
ptp([axis, out]) Peak to peak (maximum - minimum) value along a given axis.
put(indices, values[, mode]) Set a.flat[n] = values[n] for all n in indices.
ravel([order]) Return a flattened array.
repeat(repeats[, axis]) Repeat elements of an array.
reshape(shape[, order]) Returns an array containing the same data with a new shape.
resize(new_shape[, refcheck]) Change shape and size of array in-place.
round([decimals, out]) Return a with each element rounded to the given number of decimals.
searchsorted(v[, side, sorter]) Find indices where elements of v should be inserted in a to maintain order.
setfield(val, dtype[, offset]) Put a value into a specified place in a field defined by a data-type.
setflags([write, align, uic]) Set array flags WRITEABLE, ALIGNED, (WRITEBACKIFCOPY and UPDATEIFCOPY), respectively.
sort([axis, kind, order]) Sort an array, in-place.
squeeze([axis]) Remove single-dimensional entries from the shape of a.
std([axis, dtype, out, ddof, keepdims]) Returns the standard deviation of the array elements along given axis.
sum([axis, dtype, out, keepdims]) Return the sum of the array elements over the given axis.
swapaxes(axis1, axis2) Return a view of the array with axis1 and axis2 interchanged.
take(indices[, axis, out, mode]) Return an array formed from the elements of a at the given indices.
tobytes([order]) Construct Python bytes containing the raw data bytes in the array.
tofile(fid[, sep, format]) Write array to a file as text or binary (default).
tolist() Return the array as a (possibly nested) list.
tostring([order]) Construct Python bytes containing the raw data bytes in the array.
trace([offset, axis1, axis2, dtype, out]) Return the sum along diagonals of the array.
transpose(*axes) Returns a view of the array with axes transposed.
var([axis, dtype, out, ddof, keepdims]) Returns the variance of the array elements, along given axis.
view([dtype, type]) ビューを返します.コピーと異なり,データをメモリーにコピーしません.[具体例]

テクニック

  • 最大値のインデックス配列の最大の要素のインデックスを求めます.以下の例は,配列 arr の要素の最大値のインデックスを max_index に格納します.最大値のインデックスが複数有る場合,max_index 配列になります.(プログラム例)
    max_indexes = np.argwhere(arr == arr.max())
  • 最も値が近いインデックスある特定の値に最も近いインデックスを求めます.以下の例は,配列 arr の要素の中で値 value に最も近いインデックス nearelt_idx が得られます.
  • nearest_index = (np.abs(array - value)).argmin()

ページ作成情報

参考資料

  1. 本ページの作成には,以下の書籍を参考にしました.
    科学技術計算のためのPython入門   開発基礎、必須ライブラリ、高速化
    中久喜 健司
    技術評論社
    売り上げランキング: 16,041

更新履歴

2017年6月11日 ページの新規作成


no counter