2014-10-29 31 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