2014-10-29 61 views
3

我在NumPy中有一個一維數組,隱式表示一些行 - 主要順序的二維數據。這裏有一個簡單的例子:將1D NumPy數組從(隱式)行主要更改爲列主要次序

import numpy as np 
# My data looks like [[1,2,3,4], [5,6,7,8]] 
a = np.array([1,2,3,4,5,6,7,8]) 

我想在列主順序一維數組(即b = [1,5,2,6,3,7,4,8]在上面的例子)。 通常情況下,我只想做到以下幾點:

mat = np.reshape(a, (-1,4)) 
b = mat.flatten('F') 

不幸的是,我的輸入數組的長度是不行的長度我想(即a = [1,2,3,4,5,6,7])的整數倍,所以我不能叫reshape。不過,我想保留這些額外的數據,這可能相當多,因爲我的行很長。在NumPy中有沒有直接的方法可以做到這一點?

回答

1

使用一些值來表示null,以使數組成爲您想要分割它的倍數。如果轉換爲浮點數是可接受的,則可以使用nan來表示表示空值的添加元素。然後重塑2D,調用轉置,並重塑爲1D。然後消除空值。

import numpy as np 
a = np.array([1,2,3,4,5,6,7]) # input 
b = np.concatenate((a, [np.NaN])) # add a NaN to make it 8 = 4x2 
c = b.reshape(2,4).transpose().reshape(8,) # reshape to 2x4, transpose, reshape to 8x1 
d = c[-np.isnan(c)] # remove NaN 
print d 

[ 1. 5. 2. 6. 3. 7. 4.] 
2

我能想到的最簡單的方法是不嘗試使用reshape與方法,如ravel('F'),只是來連接你的陣列的切片意見。

例如:

>>> cols = 4 
>>> a = np.array([1,2,3,4,5,6,7]) 
>>> np.concatenate([a[i::cols] for i in range(cols)]) 
array([1, 5, 2, 6, 3, 7, 4]) 

這適用於陣列的任何長度和任何數量的列:

>>> cols = 5 
>>> b = np.arange(17) 
>>> np.concatenate([b[i::cols] for i in range(cols)]) 
array([ 0, 5, 10, 15, 1, 6, 11, 16, 2, 7, 12, 3, 8, 13, 4, 9, 14]) 

或者,使用as_strided重塑。事實上,該陣列a太小,以適應(2, 4)形狀並不重要:你只收到垃圾(即無論在內存中的)最後一位:

>>> np.lib.stride_tricks.as_strided(a, shape=(2, 4)) 
array([[  1,   2,   3,   4], 
     [  5,   6,   7, 168430121]]) 

>>> _.flatten('F')[:7] 
array([1, 5, 2, 6, 3, 7, 4]) 

在一般情況下,給定陣列b和列所需數量的cols你可以這樣做:

>>> x = np.lib.stride_tricks.as_strided(b, shape=(len(b)//cols + 1, cols)) # reshape to min 2d array needed to hold array b 
>>> np.concatenate((x[:,:len(b)%cols].ravel('F'), x[:-1, len(b)%cols:].ravel('F'))) 

這揭開了陣列的「好」的一部分(這些列不包含垃圾值)和壞的部分(除垃圾值這位於最下面一行)並連接兩個解開的數組。例如:

>>> cols = 5 
>>> b = np.arange(17) 
>>> x = np.lib.stride_tricks.as_strided(b, shape=(len(b)//cols + 1, cols)) 
>>> np.concatenate((x[:,:len(b)%cols].ravel('F'), x[:-1, len(b)%cols:].ravel('F'))) 
array([ 0, 5, 10, 15, 1, 6, 11, 16, 2, 7, 12, 3, 8, 13, 4, 9, 14]) 
+0

這適用於我們只需要填充一個數字的情況,但不幸的是我需要填充很多。在一個簡單的例子中,我可能有[1,2,3,4,5,6],所以調用'as_strided'給出[[1,2,3,4],[5,6,9325823,1204738]],這成爲[1,5,2,6,3,9325823,4,1204738] - 現在採取前6個元素不會刪除垃圾:( – 2014-10-30 21:06:32

+0

@GregOwen道歉 - 我應該解釋如何將該方法擴展到在我的答案中是一般情況,如果你感興趣的話,我現在添加它(一旦你有一個數組和列的數量,只需要兩行代碼來獲得結果!):-) – 2014-10-30 21:39:53