Python 通过多维阵列的所有一维子阵列进行迭代

Python 通过多维阵列的所有一维子阵列进行迭代,python,multidimensional-array,numpy,Python,Multidimensional Array,Numpy,在python中迭代n维数组的所有一维子数组的最快方法是什么 例如考虑三维数组: import numpy as np a = np.arange(24) a = a.reshape(2,3,4) 迭代器的期望收益序列为: a[:,0,0] a[:,0,1] .. a[:,2,3] a[0,:,0] .. a[1,:,3] a[0,0,:] .. a[1,2,:] 你的朋友是slice()对象,numpy的ndarray.\uuu getitem\uuuuuuuuu()方法,可能还有ite

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

例如考虑三维数组:

import numpy as np 
a = np.arange(24)
a = a.reshape(2,3,4)
迭代器的期望收益序列为:

a[:,0,0]
a[:,0,1]
..
a[:,2,3]
a[0,:,0]
..
a[1,:,3]
a[0,0,:]
..
a[1,2,:]

你的朋友是
slice()
对象,numpy的
ndarray.\uuu getitem\uuuuuuuuu()
方法,可能还有
itertools.chain。从\u iterable

可能有一种更有效的方法,但这应该是可行的

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]
这就产生了(我省去了一点小代码来打印这张照片的左侧…):

这里的关键是,使用(例如)
a[0,0,:]
索引
a
相当于使用
a[(0,0,切片(无))]
索引a。(这只是一般的python切片,不是特定于numpy的。为了向自己证明这一点,您可以使用
\uuu getitem\uuuu
编写一个虚拟类,并在索引虚拟类实例时打印传入的内容。)

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

但是,我们需要1D数组,因此我们需要过滤掉任何多于或少于一个
(即我们不需要
a[:,:,:]
a[0,:,:]
a[0,0,0]
等)

希望这有点道理,无论如何


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

以下是此类迭代器的紧凑实现:

def iter1d(a):
    return itertools.chain.from_iterable(
        numpy.rollaxis(a, axis, a.ndim).reshape(-1, dim)
        for axis, dim in enumerate(a.shape))
这将按照您在帖子中给出的顺序生成子数组:

for x in iter1d(a):
    print x
印刷品

[ 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]

这里的诀窍是迭代所有轴,并为每个轴将阵列重塑为二维阵列,其中的行是所需的一维子阵列。

非常好!比我的解决方案优雅(高效)多了!我试图通过您个人资料中列出的.net网址向root用户发送电子邮件。如果你不想连接,那没关系。@FM:Actually
dim.count(None)
似乎比
sum(如果item为None,dim中的item为1)
:)更具可读性。还有一个建议:用
切片(None)替换
None
的前两次出现
并删除包含第三次出现的
None
@Sven的行-这一点很好!提醒我看曲棍球时不要回答问题。。。(加油!最后一个阶段真的是个钉子咬人!)我看到的一个问题是,循环生成的大约N个点中只有1个被实际使用。当N变大时,这可能是一个问题。考虑到这一点,对于我的特定应用程序来说,这可能不是一个严重的问题。(N是每个维度的点数)@fodon-确实如此。(这就是我说“可能有更有效的方法”时的意思)@Sven的解决方案避免了这一点,并且应该更快、更具可扩展性。斯文的绝对是一条路要走。唯一的缺点是,对于不熟悉numpy的人来说,它有点不可读。
[ 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]