从ND到1D阵列

Ame*_*ina 115 python numpy

说我有一个数组a:

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

array([[1, 2, 3],
       [4, 5, 6]])
Run Code Online (Sandbox Code Playgroud)

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

b = np.reshape(a, (1,np.product(a.shape)))
Run Code Online (Sandbox Code Playgroud)

但这会回来

array([[1, 2, 3, 4, 5, 6]])
Run Code Online (Sandbox Code Playgroud)

这与以下不一样:

array([1, 2, 3, 4, 5, 6])
Run Code Online (Sandbox Code Playgroud)

我可以将此数组的第一个元素手动转换为1D数组:

b = np.reshape(a, (1,np.product(a.shape)))[0]
Run Code Online (Sandbox Code Playgroud)

但是这需要我知道原始数组有多少维度(并且在处理更高维度时连接[0])

是否存在从任意ndarray获取列/行向量的独立于维度的方法?

unu*_*tbu 244

使用np.ravel(用于1D视图)或np.flatten(用于1D副本)或np.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])
Run Code Online (Sandbox Code Playgroud)

请注意,ravel()返回viewa时候可能.因此修改b也会修改a.当1D元素在存储器中是连续ravel()view时返回a ,但是copy例如,如果a使用非单位步长切片另一个数组(例如a = x[::2]),则返回if .

如果您想要副本而不是视图,请使用

In [15]: c = a.flatten()
Run Code Online (Sandbox Code Playgroud)

如果您只想要一个迭代器,请使用np.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]
Run Code Online (Sandbox Code Playgroud)

  • <pedantic>在这个例子中,`ravel()`返回一个视图,但并不总是如此.有些情况下`ravel()`会返回一个副本.</ pedantic> (3认同)
  • a.ravel()的速度大约是a.reshape(-1)的三倍。`a.flatten()`要慢得多,因为它需要进行复制。 (2认同)

NPE*_*NPE 22

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

In [15]: b
Out[15]: array([1, 2, 3, 4, 5, 6])
Run Code Online (Sandbox Code Playgroud)

或者,简单地说:

In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])
Run Code Online (Sandbox Code Playgroud)

  • 在第一个例子中可以简单地使用`b = a.reshape(-1)`. (10认同)

hak*_*aku 8

我想查看答案中提到的函数的基准测试结果,包括unutbu 的.

还想指出numpy doc建议使用arr.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 |
+-------------+----------+-----------+-----------+-------------+
Run Code Online (Sandbox Code Playgroud)

结论

ravelandreshape(-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)
Run Code Online (Sandbox Code Playgroud)


Bik*_*ram 5

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

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)
Run Code Online (Sandbox Code Playgroud)

输出:

[1 2 3 4 5 6 7 8]