Python 在numpy.array的任意维上迭代

Python 在numpy.array的任意维上迭代,python,numpy,loops,Python,Numpy,Loops,是否有函数在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]] 但在其他维度上迭代则更难。例如,最后一个维度:

是否有函数在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]
或者更好(更快、更一般、更明确):

但是,上述第一种方法的速度似乎是
swapaxes()方法的两倍左右:

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]
的处理可能通过常规代码完成(处理
被更复杂的片段替换的情况)

但是请注意,更明确的第二种解决方案
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

我想没有功能。当我编写我的函数时,我最终采用了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,)]
我会使用以下方法:

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)

因此,如您所示,可以轻松地迭代第一个维度。对任意维度执行此操作的另一种方法是使用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以解决此问题:。大家一致认为,这还不足以添加到numpy代码库中。我认为使用np.rollaxis是最好的方法,如果你想要一个interator,用iter()包装它。

你可以使用numpy.shape来获得尺寸,然后使用range来迭代它们

n0, n1, n2 = numpy.shape(c)

for r in range(n0):
    print(c[r,:,:])

+1:非常直接,但不幸的是比简单的
c[:,:,i]
方法慢了一点(不知道为什么)。标准的NumPy语法
a[…,i]
将更轻,并且将不再需要
前导索引
@EOL,但这只适用于最后一个轴,lukas:最初的问题确实提到了“在任意维度上”迭代,而我想在最后一个维度上进行积分。如果目标是迭代最后一个维度,为什么不在范围c.T
或更一般的范围内对r使用
?此外,从numpy 1.10开始,应该可以使用。转置通常不会给出所需的行为,因为轴都是反转的(前一个轴变成了第二个轴,等等),因此在给出结果时需要另一个转置:双转置是不必要的跳跃
moveaxis
听起来不错,但是转换添加了一行代码:不清楚是否值得移动前面的最后一个轴,因为NumPy直接让您访问它(通过此答案中的代码)。
n0, n1, n2 = numpy.shape(c)

for r in range(n0):
    print(c[r,:,:])