如何将数字数组列表转换为单个数字数组?

假设我有;

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 来说,它实在是太慢了

你认为最有效的方法是什么?

267277 次浏览

一般来说,您可以沿着任何轴连接整个数组序列:

numpy.concatenate( LIST, axis=0 )

但是 必须考虑列表中每个数组的形状和维数(对于2维的3x5输出,您需要确保它们都是2维的 n 乘5数组)。如果要将1维数组连接为2维输出的行,则需要展开它们的维度。

正如 Jorge 的回答所指出的,还有在 numpy 1.10中引入的函数 stack:

numpy.stack( LIST, axis=0 )

这采用了互补的方法: 它为每个输入数组创建一个新视图,并在连接之前添加一个额外的维度(在本例中,在左侧,因此每个 n元素1D 数组成为一个1 × n2D 数组)。只有当所有的输入数组都具有相同的形状时,它才会工作。

vstack(或者相当于 row_stack)通常是一个更容易使用的解决方案,因为它将采用一个一维和/或二维数组序列,并在必要的地方自动扩展维度,只有在必要的地方,然后将整个列表连接在一起。如果需要新的维度,则将其添加到左侧。同样,您可以一次连接一个完整的列表,而不需要迭代:

numpy.vstack( LIST )

语法快捷方式 numpy.r_[ array1, ...., arrayN ](注意方括号)也显示了这种灵活的行为。这有利于连接一些显式命名的数组,但不利于您的情况,因为这种语法不会接受数组序列,比如 LIST

还有一个类似的函数 column_stack和快捷的 c_[...],用于水平(按列)堆叠,以及一个类似于 差不多的函数 hstackーー尽管由于某种原因后者不那么灵活(它对输入阵列的维数更严格,并试图将1-D 阵列端到端连接起来,而不是将它们视为列)。

最后,在1-D 数组的垂直堆叠的具体情况下,以下方法也可以起作用:

numpy.array( LIST )

... 因为数组可以从其他数组的序列中构造出来,在开头添加一个新的维度。

从 NumPy 版本1.10开始,我们有了 方法,它可以堆叠任意维度的数组(所有维度都相等) :

# 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

好好享受吧,

我检查了一些速度性能的方法,发现 < strong > 没有区别! 唯一的区别是,使用一些方法,您必须仔细检查尺寸。

时间:

|------------|----------------|-------------------|
|            | 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.stacknp.array更多的2d 数组,那么会产生额外的维数-result. form 是(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函数:

Asarray (LIST)

我发现了一个更健壮的数字函数 reshape

stackvstack的问题是,它对于空列表失败。

>>> 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

另一种选择是重塑

>>> s = np.reshape(LIST, (len(LIST),5))
>>> s.shape
(3, 5)
>>> LIST = []
>>> s = np.reshape(LIST, (len(LIST),5))
>>> s.shape
(0,5)

缺点是,您需要知道内部数组的长度/形状