将1D NumPy数组从(隐式)行major更改为列主要顺序

时间:2014-10-29 01:45:20

标签: python arrays numpy

我在NumPy中有一个1D数组,它隐式地表示行主要顺序的一些2D数据。这是一个简单的例子:

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中有没有直接的方法呢?

2 个答案:

答案 0 :(得分: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])

答案 1 :(得分:1)

使用某个值表示null,使数组成为您想要拆分数的倍数。如果可以接受cast to float,则可以使用nan来表示代表null的添加元素。然后重塑为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.]