2011-04-16 115 views
9

什麼是在python中遍歷n維數組的所有一維子數組的最快方法。通過多維數組的所有1維子陣列進行迭代

例如,考慮3-d數組:

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,:] 

回答

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)) 

這將產生在您在您的文章一聲令子陣:

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] 

這裏的竅門是遍歷所有軸,並且對於每個軸重塑陣列的二維陣列的行,其中在期望的一維子陣列。

+0

非常好!比我的解決方案更優雅(更高效)! – 2011-04-16 19:24:26

+0

真棒解決方案! – fodon 2011-04-16 22:24:29

+0

我試圖向您發送一封電子郵件給您的個人資料上列出的.net網址的root用戶。如果你不想連接,那很好。 – fodon 2011-04-17 16:40:24

0

你的朋友都是slice()對象,numpy的的ndarray.__getitem__()方法,以及可能itertools.chain.from_iterable

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] 

這個收益率(我要離開了代碼瑣碎位來打印這左邊... ):

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] 

這裏的關鍵是,索引a與(例如)a[0,0,:]等同於用a[(0,0,slice(None))]索引一個。 (這只是一般的python切片,沒有任何特定的numpy,爲了向你自己證明,你可以編寫一個虛擬類,只需要一個__getitem__,並打印當你索引虛擬類的實例時傳入的內容。

所以,我們想要的是每個軸的0到nx,0到ny,0到nz等等和None的每種可能組合。

但是,我們希望一維數組,所以我們需要過濾掉任何與多於或少於一個None(即我們不想a[:,:,:]a[0,:,:]a[0,0,0]等)。

希望這有一定道理,反正...

編輯:我假設的確切順序並不重要...如果你需要的確切命令你在你的問題一一列出,你會需要修改這個...

+0

@FM - 好點,這更可讀。謝謝! – 2011-04-16 18:15:53

+1

@FM:實際上'dim.count(無)'看起來比'總和(如果物品爲無,則爲暗物品1)'' – 2011-04-16 19:26:29

+0

@Sven - 再一次,優點!我忽略了顯而易見的,那裏... – 2011-04-16 19:34:13