2015-08-22 26 views
1

我試圖將2D ndarray視圖作爲記錄或結構化陣列進行復制。這似乎很好地工作,如果a擁有它的數據獲取ndarray的重新陣列視圖(也可以是視圖)

>>> a = np.array([[ 1, 391, 14, 26], 
       [ 17, 371, 15, 30], 
       [641, 340, 4, 7]]) 
>>> b = a.view(zip('abcd',[a.dtype]*4)) 
array([[(1, 391, 14, 26)], 
     [(17, 371, 15, 30)], 
     [(641, 340, 4, 7)]], 
     dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<i8'), ('d', '<i8')]) 
>>> b.base is a 
True 

但如果a已經是一個視圖,這個失敗。這裏有一個例子

>>> b = a[:,[0,2,1,3]] 
>>> b.base is None 
False 
>>> b.view(zip('abcd',[a.dtype]*4)) 
ValueError: new type not compatible with array. 

有趣的是,在這種情況下b.base是視圖

>>> (b.base == b.T).all() 
True 

的轉置因此它是有道理的numpy的無法創建的那個我想要的視圖。

但是,如果我用

>>> b = np.take(a,[0,2,1,3],axis=1) 

這導致b是數據的正確副本,以便採取recarray觀點的作品。側面問題:有人可以解釋這種行爲與花式索引相反嗎?

我的問題是,我這樣做是錯誤的嗎?正在考慮我不支持的方式嗎?如果是這樣,那麼正確的做法是什麼?

回答

1

(大編輯)

bF_CONTINGUOUS(見b.flags)。在視場的數目,然後需要匹配的b行數,而不是列的數目:

In [204]: b=a[:,[0,2,1,3]].view('i4,i4,i4') 
In [205]: b 
Out[205]: 
array([[(0, 4, 8), (2, 6, 10), (1, 5, 9), (3, 7, 11)]], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')]) 

一個更簡單的情況下是a.copy(order='F').view('i4,i4,i4')

np.take(a,[0,2,1,3],axis=1)a[:,[0,2,1,3]].copy()產生C_CONTIGUOUS副本,並且因此可以用4個字段查看。

還請注意b.base有3列。


(解決這個問題前面絆)

做一個觀點是不是一個問題。

a = np.arange(12).reshape(3,4) 
a.view('i4,i4,i4,i4') 

沒有問題。

使第一b的副本也可以工作:

b=a[:,[0,2,1,3]].copy() 
b.view('i4,i4,i4,i4') 

首屆b(無複印件)是F_CONTIGUOUS(看b.flags)。這就是您的b.base == b.T顯示的內容。

np.take產生與bcopy相同種類的陣列 - 即相同的標誌和相同的__array_interface__顯示。

a[[0,2,1],:].view('i4,i4,i4,i4') 
a.T[[0,2,1,3],:].T.view('i4,i4,i4,i4') 

如果我換成純數組索引的混合切片和數組索引:

a[[[0],[1],[2]],[0,2,1,3]].view('i4,i4,i4,i4') 

結果是C_CONTIGUOUS

是工作以外的事情。因此,我還沒有解釋[:, [...]]中的詳細信息 - 具體說明爲什麼它會生成F_CONTIGUOUS副本。

混合基本/高級索引文檔部分確實警告存儲器佈局可以改變:

http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing

在最簡單的情況下,僅存在單一的先進索引。例如,單個高級索引可以替換切片,並且結果數組將是相同的,但是,它是一個副本並且可能具有不同的內存佈局。如果可能,切片是優選的。

+0

謝謝!我不知道內存佈局可能會這樣改變。清楚的是,我知道索引像'a [:,[0,2,1,3]'會返回一個副本,但我不知道它可能是'F_CONTIGOUS'或'np.take'會總是返回一個'C_CONTIGUOUS'(這個numpy文檔說''np.take'與花式索引做同樣的事情,這在這個例子中似乎是錯誤的)。你會如何處理這種特殊的觀點(沒有複製),並且始終有效?檢查數組是否爲'F \ C_CONTIGOUS'是不好的做法嗎? – toes