2017-01-01 75 views
1

我正在編寫一個程序,該程序假設能夠導入某些較高維度的numpy數組,例如,類似於陣列a:選擇要在一個numpy數組中索引的維數

a = numpy.zeros([3,5,7,2]) 

此外,每個維度將對應於某個物理維度,例如,頻率,距離......我還將導入包含這些尺寸信息的陣列,例如爲一個以上:

freq = [1,2,3] 
time = [0,1,2,3,4,5,6] 
distance = [0,0,0,4,1] 
angle = [0,180] 
從這個例子

顯然和簽名可以計算出,頻率屬於維度0,時間維度2等。但由於這事先不知道,所以我可以採取像頻率片

a_f1 = a[1,:,:,:] 

因爲我不知道哪個維度的頻率索引。

所以,我想要的是有一些方法來選擇索引索引的維度;在某些Python'ish代碼中有些類似於

a_f1 = a.get_slice([0,], [[1],]) 

這是假設從維度0和完整的其他維度返回索引1的切片。

a_p = a[0, 1:, ::2, :-1] 

隨後將對應於類似

a_p = a.get_slice([0, 1, 2, 3], [[0,], [1,2,3,4], [0,2,4,6], [0,]]) 
+0

你以爲你知道如何提前多少維度有?也就是說,對於你的'a.get_slice([0,],[[1],])',你知道應該有三個「完全的其他維度」嗎? – BrenBarn

+0

@BrenBarn呃,可能是那種語法。我只是提出了語法來說明我需要什麼。 – Robert

+0

我覺得這篇關於熊貓的文章[分層索引(MultiIndex)](http://pandas.pydata.org/pandas-docs/stable/advanced.html)可能很有趣。 –

回答

1

您可以輕而易舉地構建索引的元組,使用slice對象在需要的地方,然後用它來索引你的數組。基本是配方是:

indices = { 
    0: # put here whatever you want to get on dimension 0, 
    1: # put here whatever you want to get on dimension 1, 
    # leave out whatever dimensions you want to get all of 
} 
ix = [indices.get(dim, slice(None)) for dim in range(arr.ndim)] 
arr[ix] 

在這裏,我有一本字典做它,因爲我認爲這使得它更容易看到它的尺寸與索引去。

與示例數據

所以:

x = np.zeros([3,5,7,2]) 

我們這樣做:

indices = {0: 1} 
ix = [indices.get(dim, slice(None)) for dim in range(x.ndim)] 

>>> x[ix].shape 
(5L, 7L, 2L) 

因爲你的陣列是全零,我只是出結果的形狀表明它是我們想要什麼。 (即使不是全部爲零,這是難以閱讀文本形式的3D陣列。)

對於你的第二個例子:

indices = { 
    0: 0, 
    1: slice(1, None), 
    2: slice(None, None, 2), 
    3: slice(None, -1) 
} 
ix = [indices.get(dim, slice(None)) for dim in range(x.ndim)] 

>>> x[ix].shape 
(4L, 4L, 1L) 

你可以看到形狀對應值的數量在你的a_p例子中。需要注意的一點是,第一個維度已經消失,因爲您只爲該索引指定了一個值。最後一個維度仍然存在,但長度爲1,因爲您指定了恰好得到一個元素的切片。 (這與some_list[0]爲您提供單個值的原因相同,但some_list[:1]爲您提供了一個元素列表。)

0

您可以使用advanced indexing來實現此目的。

需要對每個維度的索引進行適當的整形,以便索引可以在陣列中正確傳播。例如,三維數組的第一個維度的索引需要形成(x, 1, 1),以便它將在第一維上進行廣播。三維陣列的第二維的索引需要形成(1, y, 1),以便它將在第二維上進行廣播。

import numpy as np 
a = np.zeros([3,5,7,2]) 
b = a[0, 1:, ::2, :-1] 

indices = [[0,], [1,2,3,4], [0,2,4,6], [0,]] 
def get_aslice(a, indices): 
    n_dim_ = len(indices) 
    index_array = [np.array(thing) for thing in indices] 
    idx = [] 
    # reshape the arrays by adding single-dimensional entries 
    # based on the position in the index array 
    for d, thing in enumerate(index_array): 
     shape = [1] * n_dim_ 
     shape[d] = thing.shape[0] 
     #print(d, shape) 
     idx.append(thing.reshape(shape)) 

    c = a[idx] 

    # to remove leading single-dimensional entries from the shape 
    #while c.shape[0] == 1: 
    # c = np.squeeze(c, 0) 

    # To remove all single-dimensional entries from the shape 
    #c = np.squeeze(c).shape 

    return c 

對於a作爲輸入,則返回具有形狀的陣列(1,4,4,1)的a_p例如具有(4,4,1)的形狀。如果需要刪除額外的維度,請取消註釋函數中的np.squeeze行。


現在我覺得很傻。在閱讀文檔我注意到numpy的有一個指數例行程序,你想要做什麼 - numpy.ix_

>>> a = numpy.zeros([3,5,7,2]) 
>>> indices = [[0,], [1,2,3,4], [0,2,4,6], [0,]] 
>>> index_arrays = np.ix_(*indices) 
>>> a_p = a[index_arrays] 
>>> a_p.shape 
(1, 4, 4, 1) 
>>> a_p = np.squeeze(a_p) 
>>> a_p.shape 
(4, 4) 
>>> 
+0

你在'indices'中顯示的是他希望作爲*結果*的內容,但他不想指定那個;他只想指定「我想索引1在維度0」,並讓它自動創建「索引」。 – BrenBarn

+0

@brenbarn,那我完全誤解了。 – wwii

+0

哎呀,我想我其實誤解了。他的例子確實顯示你的事情。但作爲一個例子,它有點奇怪,因爲它並行的是指定切片,而不是實際的索引。 '.ix_'是否適用於切片?另外,如果你不想在所有維上指定索引,它是否工作? – BrenBarn

相關問題