迭代通过多维数组的所有1维子阵列

fod*_*don 9 python numpy multidimensional-array

在python中迭代遍历n维数组的所有一维子数组的最快方法是什么.

例如,考虑三维数组:

import numpy as np 
a = np.arange(24)
a = a.reshape(2,3,4)
Run Code Online (Sandbox Code Playgroud)

迭代器所需的产量序列是:

a[:,0,0]
a[:,0,1]
..
a[:,2,3]
a[0,:,0]
..
a[1,:,3]
a[0,0,:]
..
a[1,2,:]
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 10

这是一个这样的迭代器的紧凑实现:

def iter1d(a):
    return itertools.chain.from_iterable(
        numpy.rollaxis(a, axis, a.ndim).reshape(-1, dim)
        for axis, dim in enumerate(a.shape))
Run Code Online (Sandbox Code Playgroud)

这将按照您在帖子中给出的顺序产生子数组:

for x in iter1d(a):
    print x
Run Code Online (Sandbox Code Playgroud)

版画

[ 0 12]
[ 1 13]
[ 2 14]
[ 3 15]
[ 4 16]
[ 5 17]
[ 6 18]
[ 7 19]
[ 8 20]
[ 9 21]
[10 22]
[11 23]
[0 4 8]
[1 5 9]
[ 2  6 10]
[ 3  7 11]
[12 16 20]
[13 17 21]
[14 18 22]
[15 19 23]
[0 1 2 3]
[4 5 6 7]
[ 8  9 10 11]
[12 13 14 15]
[16 17 18 19]
[20 21 22 23]
Run Code Online (Sandbox Code Playgroud)

这里的技巧是迭代所有轴,并且对于每个轴,将阵列重新整形为二维阵列,其行是期望的一维子阵列.


Joe*_*ton 5

可能有一种更有效的方式,但这应该有效......

import itertools
import numpy as np

a = np.arange(24)
a = a.reshape(2,3,4)

colon = slice(None)
dimensions = [range(dim) + [colon] for dim in a.shape]

for dim in itertools.product(*dimensions):
    if dim.count(colon) == 1:
        print a[dim]
Run Code Online (Sandbox Code Playgroud)

这会产生(我只留下一些微不足道的代码来打印这个...的左侧):

a[0,0,:] -->  [0 1 2 3]
a[0,1,:] -->  [4 5 6 7]
a[0,2,:] -->  [ 8  9 10 11]
a[0,:,0] -->  [0 4 8]
a[0,:,1] -->  [1 5 9]
a[0,:,2] -->  [ 2  6 10]
a[0,:,3] -->  [ 3  7 11]
a[1,0,:] -->  [12 13 14 15]
a[1,1,:] -->  [16 17 18 19]
a[1,2,:] -->  [20 21 22 23]
a[1,:,0] -->  [12 16 20]
a[1,:,1] -->  [13 17 21]
a[1,:,2] -->  [14 18 22]
a[1,:,3] -->  [15 19 23]
a[:,0,0] -->  [ 0 12]
a[:,0,1] -->  [ 1 13]
a[:,0,2] -->  [ 2 14]
a[:,0,3] -->  [ 3 15]
a[:,1,0] -->  [ 4 16]
a[:,1,1] -->  [ 5 17]
a[:,1,2] -->  [ 6 18]
a[:,1,3] -->  [ 7 19]
a[:,2,0] -->  [ 8 20]
a[:,2,1] -->  [ 9 21]
a[:,2,2] -->  [10 22]
a[:,2,3] -->  [11 23]
Run Code Online (Sandbox Code Playgroud)

这里的关键是a使用(例如)a[0,0,:]索引等效于索引a a[(0,0,slice(None))].(这只是通用的python切片,没有特定的numpy特定.为了向自己证明,你可以编写一个只有a的虚拟类,__getitem__并在索引虚拟类的实例时打印传入的内容.).

因此,我们想要的是0到nx,0到ny,0到nz等的每种可能组合以及None每个轴的a.

但是,我们希望一维数组,所以我们需要过滤掉任何东西更多或小于一None(即我们不希望a[:,:,:],a[0,:,:],a[0,0,0]等).

无论如何,希望这是有道理的......

编辑:我假设确切的顺序无关紧要......如果您需要在问题中列出的确切顺序,则需要修改此...