假设我有:
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])] # inner lists are numpy arrays
我试图进行转换;
array([[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5])
目前我正在通过在vstack上进行迭代来解决它,但对于特别大的LIST来说,速度非常慢。
您认为最有效的方法是什么?
numpy.concatenate( LIST, axis=0 )
numpy.stack( LIST, axis=0 )
numpy.vstack( LIST )
numpy.r_[ array1, ...., arrayN ]
(注意方括号)来展示。这对于连接几个明确命名的数组很好,但在您的情况下,它变得不太可读,因为[]
下标不接受list
。您需要将序列转换为tuple
:numpy.r_[tuple(LIST)]
。使用vstack()
更易读。column_stack
和快捷方式c_[...]
,用于水平(按列)堆叠,以及一个几乎类似的函数hstack
,尽管由于某种原因,后者不太灵活(它对输入数组的维度要求更严格,并尝试将1-D数组首尾相连而不是将它们视为列)。numpy.array( LIST )
从NumPy 1.10版本开始,我们拥有了 stack 方法。它可以堆叠任何维度相同的数组:
# List of arrays.
L = [np.random.randn(5,4,2,5,1,2) for i in range(10)]
# Stack them using axis=0.
M = np.stack(L)
M.shape # == (10,5,4,2,5,1,2)
np.all(M == L) # == True
M = np.stack(L, axis=1)
M.shape # == (5,10,4,2,5,1,2)
np.all(M == L) # == False (Don't Panic)
# This are all true
np.all(M[:,0,:] == L[0]) # == True
all(np.all(M[:,i,:] == L[i]) for i in range(10)) # == True
享受吧,
时间:
|------------|----------------|-------------------|
| | shape (10000) | shape (1,10000) |
|------------|----------------|-------------------|
| np.concat | 0.18280 | 0.17960 |
|------------|----------------|-------------------|
| np.stack | 0.21501 | 0.16465 |
|------------|----------------|-------------------|
| np.vstack | 0.21501 | 0.17181 |
|------------|----------------|-------------------|
| np.array | 0.21656 | 0.16833 |
|------------|----------------|-------------------|
您可以看到我尝试了两个实验 - 使用 np.random.rand(10000)
和 np.random.rand(1, 10000)
如果我们使用二维数组,则np.stack
和np.array
会创建额外的维度 - 结果形状为(1,10000,10000)和(10000,1,10000),因此它们需要额外的操作来避免这种情况。
代码:
from time import perf_counter
from tqdm import tqdm_notebook
import numpy as np
l = []
for i in tqdm_notebook(range(10000)):
new_np = np.random.rand(10000)
l.append(new_np)
start = perf_counter()
stack = np.stack(l, axis=0 )
print(f'np.stack: {perf_counter() - start:.5f}')
start = perf_counter()
vstack = np.vstack(l)
print(f'np.vstack: {perf_counter() - start:.5f}')
start = perf_counter()
wrap = np.array(l)
print(f'np.array: {perf_counter() - start:.5f}')
start = perf_counter()
l = [el.reshape(1,-1) for el in l]
conc = np.concatenate(l, axis=0 )
print(f'np.concatenate: {perf_counter() - start:.5f}')
另一种解决方法是使用 asarray
函数:
numpy.asarray( LIST )
reshape
。
stack
和vstack
的问题在于,它们无法处理空列表。>>> LIST = [np.array([1, 2, 3, 4, 5]), np.array([1, 2, 3, 4, 5]),np.array([1,2,3,4,5])]
>>> s = np.vstack(LIST)
>>> s.shape
(3, 5)
>>> s = np.vstack([])
ValueError: need at least one array to concatenate
另一种选择是reshape
>>> s = np.reshape(LIST, (len(LIST),5))
>>> s.shape
(3, 5)
>>> LIST = []
>>> s = np.reshape(LIST, (len(LIST),5))
>>> s.shape
(0,5)
缺点是,你需要知道内部数组的长度/形状
array
是该框架中常见的对象之一。如果OP执行了from numpy import array
,那么就是正确的。同意Hedwin上面的评论,没有理由因为问题需要一些关于Python生态系统中实际上是标准库一部分的知识而对OP不友善。 - AmphotericLewisAcid