Numpy配列の任意の次元で反復子を取得する関数はありますか?
最初の次元の繰り返しは簡単です...
In [63]: c = numpy.arange(24).reshape(2,3,4)
In [64]: for r in c :
....: print r
....:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
しかし、他の次元を反復することはより困難です。たとえば、最後の次元:
In [73]: for r in c.swapaxes(2,0).swapaxes(1,2) :
....: print r
....:
[[ 0 4 8]
[12 16 20]]
[[ 1 5 9]
[13 17 21]]
[[ 2 6 10]
[14 18 22]]
[[ 3 7 11]
[15 19 23]]
私は自分でこれを行うジェネレーターを作成していますが、これを自動的に行うnumpy.ndarray.iterdim(axis = 0)などの名前の関数がないことに驚いています。
提案するのは非常に高速ですが、より明確なフォームを使用すると読みやすさを改善できます。
_for i in range(c.shape[-1]):
print c[:,:,i]
_
または、より良い(より速く、より一般的で、より明確に):
_for i in range(c.shape[-1]):
print c[...,i]
_
ただし、上記の最初のアプローチは、swapaxes()
アプローチの約2倍遅いようです。
_python -m timeit -s 'import numpy; c = numpy.arange(24).reshape(2,3,4)' \
'for r in c.swapaxes(2,0).swapaxes(1,2): u = r'
100000 loops, best of 3: 3.69 usec per loop
python -m timeit -s 'import numpy; c = numpy.arange(24).reshape(2,3,4)' \
'for i in range(c.shape[-1]): u = c[:,:,i]'
100000 loops, best of 3: 6.08 usec per loop
python -m timeit -s 'import numpy; c = numpy.arange(24).reshape(2,3,4)' \
'for r in numpy.rollaxis(c, 2): u = r'
100000 loops, best of 3: 6.46 usec per loop
_
これはswapaxes()
がデータをコピーせず、_c[:,:,i]
_の処理が一般的なコード(_:
_がより複雑なスライス)。
ただし、より明示的な2番目のソリューション_c[...,i]
_は非常に読みやすく、非常に高速であることに注意してください。
_python -m timeit -s 'import numpy; c = numpy.arange(24).reshape(2,3,4)' \
'for i in range(c.shape[-1]): u = c[...,i]'
100000 loops, best of 3: 4.74 usec per loop
_
私は次のものを使用します:
_c = numpy.arange(2 * 3 * 4)
c.shape = (2, 3, 4)
for r in numpy.rollaxis(c, 2):
print(r)
_
関数rollaxisは、配列に新しいビューを作成します。この場合、軸2を前に移動します。これはc.transpose(2, 0, 1)
操作に相当します。
したがって、最初に示したように、1次元を簡単に反復処理できます。任意の次元でこれを行う別の方法は、numpy.rollaxis()を使用して指定された次元を最初(デフォルトの動作)にし、返された配列(ビューであるため高速です)を反復子として使用することです。 。
In [1]: array = numpy.arange(24).reshape(2,3,4)
In [2]: for array_slice in np.rollaxis(array, 1):
....: print array_slice.shape
....:
(2, 4)
(2, 4)
(2, 4)
編集:私はここでこれに対処するためにnumpyにPRを提出したとコメントします: https://github.com/numpy/numpy/pull/3262 。コンセンサスは、これはnumpyコードベースに追加するには不十分であるということでした。これを行うには、np.rollaxisを使用するのが最善の方法だと思います。インターレーターが必要な場合は、iter()でラップします。
機能がないと思います。私が関数を書いたとき、私はEOLも提案した反復を採用することになりました。将来の読者のために、ここにあります:
def iterdim(a, axis=0) :
a = numpy.asarray(a);
leading_indices = (slice(None),)*axis
for i in xrange(a.shape[axis]) :
yield a[leading_indices+(i,)]
Numpy.shapeを使用して寸法を取得し、範囲を使用して寸法を反復できます。
n0, n1, n2 = numpy.shape(c)
for r in range(n0):
print(c[r,:,:])