NumPy 配列の反復

NumPy のイテレータオブジェクト numpy.nditer は、1つまたは複数の配列要素に柔軟にアクセスする方法を提供します。

イテレータの最も基本的なタスクは、配列要素へのアクセスを完了できることです。

次に、arange() 関数を使用して 2X3 配列を作成し、nditer を使用してそれを反復します。

実例

import numpy as np a = np.arange(6).reshape(2,3) print ('元の配列は:') print (a) print ('\n') print ('反復出力要素:') for x in np.nditer(a): print (x, end=", " ) print ('\n')

出力結果は:

原始数组是:
[[0 1 2]
 [3 4 5]]


迭代输出元素:
0, 1, 2, 3, 4, 5, 

上記の例では、標準のCまたはFortranの順序を使用していません。選択された順序は配列のメモリレイアウトと一致しています。これはアクセス効率を向上させるためであり、デフォルトは行優先順(row-major order、またはC-order)です。

これは、デフォルトでは各要素にアクセスするだけで、特定の順序を考慮する必要がないことを反映しています。このことは、上記の配列の転置を反復し、C順序で配列の転置にアクセスするcopy方式と比較することで確認できます。次の例をご覧ください。

実例

import numpy as np a = np.arange(6).reshape(2,3) for x in np.nditer(a.T): print (x, end=", " ) print ('\n') for x in np.nditer(a.T.copy(order='C')): print (x, end=", " ) print ('\n')

出力結果は:

0, 1, 2, 3, 4, 5, 

0, 3, 1, 4, 2, 5, 

上記の例から、a と a.T の走査順序は同じであり、つまりメモリ内の格納順序も同じであることがわかります。しかし、a.T.copy(order = 'C')の走査結果は異なります。それは、前の2つとは格納方式が異なるためであり、デフォルトでは行単位でアクセスされるからです。

走査順序の制御

  • for x in np.nditer(a, order='F'):Fortran order、すなわち列優先順です。
  • for x in np.nditer(a.T, order='C'):C order、すなわち行優先順です。

実例

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('元の配列は:') print (a) print ('\n') print ('元の配列の転置は:') b = a.T print (b) print ('\n') print ('C スタイルの順序で走査:') c = b.copy(order='C') print (c) for x in np.nditer(c): print (x, end=", " ) print ('\n') print ('F スタイルの順序で走査:') c = b.copy(order='F') print (c) for x in np.nditer(c): print (x, end=", " )

出力結果は:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


原始数组的转置是:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]


以 C 风格顺序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, 

以 F 风格顺序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55,

明示的に設定することで、nditer オブジェクトに特定の順序を強制できます:

実例

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('元の配列は:') print (a) print ('\n') print ('C スタイルの順序で走査:') for x in np.nditer(a, order = 'C'): print (x, end=", " ) print ('\n') print ('F スタイルの順序で走査:') for x in np.nditer(a, order = 'F'): print (x, end=", " )

出力結果は:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


以 C 风格顺序排序:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 

以 F 风格顺序排序:
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,

配列内の要素の値を変更する

nditer オブジェクトには別のオプションパラメータ op_flags があります。デフォルトでは、nditer は反復対象の配列を読み取り専用オブジェクト(read-only)として扱います。配列を反復しながら配列要素の値を変更するには、readwrite または writeonly モードを指定する必要があります。

実例

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('元の配列は:') print (a) print ('\n') for x in np.nditer(a, op_flags=['readwrite']): x[...]=2*x print ('変更後の配列は:') print (a)

出力結果は:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


修改后的数组是:
[[  0  10  20  30]
 [ 40  50  60  70]
 [ 80  90 100 110]]

外部ループの使用

nditer クラスのコンストラクタには flags パラメータがあり、次の値を受け取ることができます:

パラメータ 説明
c_index C 順序のインデックスを追跡できます。
f_index Fortran 順序のインデックスを追跡できます。
multi_index 各反復で1つのインデックスタイプを追跡できます。
external_loop 指定される値は、ゼロ次元配列ではなく、複数の値を持つ1次元配列です。

次の例では、イテレータは各列に対応して走査し、1次元配列に結合します。

実例

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('元の配列は:') print (a) print ('\n') print ('変更後の配列は:') for x in np.nditer(a, flags = ['external_loop'], order = 'F'): print (x, end=", " )

出力結果は:

原始数组是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


修改后的数组是:
[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],

ブロードキャスト反復

2つの配列がブロードキャスト可能であれば、nditer 結合オブジェクトはそれらを同時に反復できます。配列 a の次元が 3X4、配列 b の次元が 1X4 であると仮定すると、次のイテレータを使用します(配列 b は a のサイズにブロードキャストされます)。

実例

import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('最初の配列は:') print (a) print ('\n') print ('2番目の配列は:') b = np.array([1, 2, 3, 4], dtype = int) print (b) print ('\n') print ('変更後の配列は:') for x,y in np.nditer([a,b]): print ("%d:%d" % (x,y), end=", " )

出力結果は:

第一个数组为:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]


第二个数组为:
[1 2 3 4]


修改后的数组为:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,
その他の拡張