从ND到一维阵列


141

说我有一个数组a

a = np.array([[1,2,3], [4,5,6]])

array([[1, 2, 3],
       [4, 5, 6]])

我想将其转换为一维数组(即列向量):

b = np.reshape(a, (1,np.product(a.shape)))

但这又回来了

array([[1, 2, 3, 4, 5, 6]])

这与以下内容不同:

array([1, 2, 3, 4, 5, 6])

我可以使用此数组的第一个元素将其手动转换为一维数组:

b = np.reshape(a, (1,np.product(a.shape)))[0]

但这需要我知道原始数组有多少个维数(并在使用较大维数时将[0]连接起来)

有没有一种与尺寸无关的方式来从任意ndarray获取列/行向量?

Answers:


277

使用np.ravel(用于1D视图)或np.ndarray.flatten(用于1D副本)或np.ndarray.flat(用于1D迭代器):

In [12]: a = np.array([[1,2,3], [4,5,6]])

In [13]: b = a.ravel()

In [14]: b
Out[14]: array([1, 2, 3, 4, 5, 6])

请注意,ravel()返回viewa时候可能。因此修改b也会修改aravel()返回一个view当1D元件在存储器中连续,但将返回copy,如果,例如,a是从使用非单元的步长(例如切片另一个阵列制成a = x[::2])。

如果要复制而不是视图,请使用

In [15]: c = a.flatten()

如果只需要迭代器,请使用np.ndarray.flat

In [20]: d = a.flat

In [21]: d
Out[21]: <numpy.flatiter object at 0x8ec2068>

In [22]: list(d)
Out[22]: [1, 2, 3, 4, 5, 6]

4
<pedantic>在此示例中,ravel()返回一个视图,但这并不总是正确的。在某些情况下会ravel()返回副本。</ pedantic>
Warren Weckesser 2012年

3
a.ravel()看起来是速度的3倍左右a.reshape(-1)a.flatten()速度较慢,因为它需要进行复制。
BallpointBen

25
In [14]: b = np.reshape(a, (np.product(a.shape),))

In [15]: b
Out[15]: array([1, 2, 3, 4, 5, 6])

或者,简单地:

In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])

11
可以使用b = a.reshape(-1)短的第一个例子。
Syrtis Major

5

最简单的方法之一是使用flatten(),例如以下示例:

 import numpy as np

 batch_y =train_output.iloc[sample, :]
 batch_y = np.array(batch_y).flatten()

我的数组是这样的:

    0
0   6
1   6
2   5
3   4
4   3
.
.
.

使用后flatten()

array([6, 6, 5, ..., 5, 3, 6])

这也是此类错误的解决方案:

Cannot feed value of shape (100, 1) for Tensor 'input/Y:0', which has shape '(?,)' 

4

对于具有不同大小的数组列表,请使用以下命令:

import numpy as np

# ND array list with different size
a = [[1],[2,3,4,5],[6,7,8]]

# stack them
b = np.hstack(a)

print(b)

输出:

[1 2 3 4 5 6 7 8]


您将如何获得a后背的形状b
dvdblk

如果要将1D分成多个块。看到这个stackoverflow.com/a/8495740/6117565
bikram

4

我想查看答案中提到的功能(包括unutbu的功能)的基准结果。

还需要指出的是,建议在案例视图中使用numpy docarr.reshape(-1)更为可取。(即使ravel在以下结果中速度更快)


TL; DRnp.ravel是性能最高的(数量很少)。

基准测试

功能:

numpy版本:“ 1.18.0”

不同ndarray大小的执行时间

+-------------+----------+-----------+-----------+-------------+
|  function   |   10x10  |  100x100  | 1000x1000 | 10000x10000 |
+-------------+----------+-----------+-----------+-------------+
| ravel       | 0.002073 |  0.002123 |  0.002153 |    0.002077 |
| reshape(-1) | 0.002612 |  0.002635 |  0.002674 |    0.002701 |
| flatten     | 0.000810 |  0.007467 |  0.587538 |  107.321913 |
| flat        | 0.000337 |  0.000255 |  0.000227 |    0.000216 |
+-------------+----------+-----------+-----------+-------------+

结论

ravel并且reshape(-1)的执行时间是一致的,并且与ndarray的大小无关。但是,ravel速度稍快一些,但是reshape在调整大小时提供了灵活性。(也许这就是为什么numpy doc建议改用它的原因。或者在某些情况下reshape返回视图而ravel没有)。
如果要处理大尺寸的ndarray,则使用flatten可能会导致性能问题。建议不要使用它。除非您需要数据副本才能执行其他操作。

使用的代码

import timeit
setup = '''
import numpy as np
nd = np.random.randint(10, size=(10, 10))
'''

timeit.timeit('nd = np.reshape(nd, -1)', setup=setup, number=1000)
timeit.timeit('nd = np.ravel(nd)', setup=setup, number=1000)
timeit.timeit('nd = nd.flatten()', setup=setup, number=1000)
timeit.timeit('nd.flat', setup=setup, number=1000)

0

尽管这不是使用np数组格式,(为了懒惰地修改我的代码),这应该做您想要的...如果,您确实想要一个列向量,那么您将需要转置向量结果。这完全取决于您打算如何使用它。

def getVector(data_array,col):
    vector = []
    imax = len(data_array)
    for i in range(imax):
        vector.append(data_array[i][col])
    return ( vector )
a = ([1,2,3], [4,5,6])
b = getVector(a,1)
print(b)

Out>[2,5]

因此,如果需要转置,可以执行以下操作:

def transposeArray(data_array):
    # need to test if this is a 1D array 
    # can't do a len(data_array[0]) if it's 1D
    two_d = True
    if isinstance(data_array[0], list):
        dimx = len(data_array[0])
    else:
        dimx = 1
        two_d = False
    dimy = len(data_array)
    # init output transposed array
    data_array_t = [[0 for row in range(dimx)] for col in range(dimy)]
    # fill output transposed array
    for i in range(dimx):
        for j in range(dimy):
            if two_d:
                data_array_t[j][i] = data_array[i][j]
            else:
                data_array_t[j][i] = data_array[j]
    return data_array_t
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.