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

Posted

技术标签:

【中文标题】如何将 numpy 数组列表转换为单个 numpy 数组?【英文标题】:How to convert list of numpy arrays into single numpy array? 【发布时间】:2015-02-15 11:38:58 【问题描述】:

假设我有;

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 来说真的很慢

你对最有效的方法有什么建议?

【问题讨论】:

LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])] 这不是正确的 python 语法。请澄清。 【参考方案1】:

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

numpy.concatenate( LIST, axis=0 )

但是您确实必须担心列表中每个数组的形状和维度(对于二维 3x5 输出,您需要确保它们都是二维 n-by -5 个数组)。如果要将一维数组串联为二维输出的行,则需要扩展它们的维数。

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

numpy.stack( LIST, axis=0 )

这采用了互补的方法:它为每个输入数组创建一个新视图并添加一个额外的维度(在这种情况下,在左侧,因此每个 n-element 1D 数组变为 1×n二维数组)在连接之前。只有当所有输入数组都具有相同的形状时,它才会起作用——即使是沿着连接轴。

vstack(或等效的row_stack)通常是一种更易于使用的解决方案,因为它会采用一维和/或二维数组的序列,并在必要时且仅在必要时自动扩展维度,在将整个列表连接在一起之前。如果需要新维度,则将其添加到左侧。同样,您可以一次连接整个列表而无需迭代:

numpy.vstack( LIST )

这种灵活的行为也体现在语法快捷方式numpy.r_[ array1, ...., arrayN ](注意方括号)中。这对于连接一些显式命名的数组很有用,但不适合您的情况,因为这种语法不会接受数组序列,例如您的 LIST

还有一个类似的函数column_stack 和快捷方式c_[...],用于水平(按列)堆叠,以及一个几乎类似的函数hstack——尽管出于某种原因后者不太灵活(它对输入数组的维度更加严格,并尝试将一维数组端到端连接,而不是将它们视为列)。

最后,在一维数组的垂直堆叠的特定情况下,以下方法也有效:

numpy.array( LIST )

...因为数组可以由一系列其他数组构成,在开头添加一个新维度。

【讨论】:

我认为他想要一个二维数组作为输出。【参考方案2】:

从 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

享受,

【讨论】:

【参考方案3】:

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

时间:

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

如您所见,我尝试了 2 个实验 - 使用 np.random.rand(10000)np.random.rand(1, 10000) 如果我们使用二维数组而不是 np.stacknp.array 创建额外的维度 - result.shape 是 (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')

【讨论】:

【参考方案4】:

其他解决方案是使用asarray函数:

numpy.asarray(列表)

【讨论】:

以上是关于如何将 numpy 数组列表转换为单个 numpy 数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何将numpy数组列表转换为numpy数组

Python + alglib + NumPy:如何避免将数组转换为列表?

将 2d numpy 数组转换为列表列表 [重复]

如何将包含字符串列表的 numpy 数组转换为包含零和一列表的数组?

将 NumPy 数组转换为 Python 列表结构?

使用列表中的标签将 numpy 数组转换为 pandas 数据框