Numpy concatenate很慢:任何替代方法?

Adm*_*mia 6 arrays performance numpy concatenation

我正在运行以下代码:

for i in range(1000)
    My_Array=numpy.concatenate((My_Array,New_Rows[i]), axis=0)
Run Code Online (Sandbox Code Playgroud)

上面的代码很慢.有没有更快的方法?

sas*_*cha 15

这基本上是基于数组的所有算法中发生的事情.

每次更改数组的大小时,都需要调整大小,并且需要复制每个元素.这也发生在这里.(一些实现保留一些空槽;例如,随着每个增长,内部存储器的空间加倍).

  • 如果你在np.array创建时获得数据,只需一次添加这些数据(内存只分配一次!)
  • 如果没有,请使用链接列表(允许O(1)追加操作)收集它们.然后立即在你的np.array中读取它(再次只有一个内存分配).

这不是一个特定于numpy的主题,而是关于数据结构的更多内容.

编辑:由于这个相当含糊的答案得到了一些赞成,我觉得有必要明确我的链表方法就是一个可能的例子.正如评论中所指出的,python的列表更像数组(绝对不是链表).但核心事实是:python中的list.append()速度很快(摊销:O(1)),而numpy-arrays则不然!关于文档内部的一小部分:

如何实施清单?

Python的列表实际上是可变长度数组,而不是Lisp风格的链表.该实现使用对其他对象的连续引用数组,并在列表头结构中保留指向此数组和数组长度的指针.

这使得列表的索引成为[i]一种操作,其成本与列表的大小或索引的值无关.

附加或插入项目时,将调整引用数组的大小.一些聪明的东西被用来改善重复追加物品的表现 ; 当必须增长数组时,会分配一些额外的空间,因此接下来的几次不需要实际调整大小.

(我的大胆注释)

  • Python没有本机链表类. (3认同)
  • 我实际上使用了列表附加,性能得到了显着提升。 (2认同)

the*_*ter 9

也许创建一个大小正确的空数组而不是填充它?如果你有一个具有相同维度的数组列表,你可以

import numpy as np 
arr = np.zeros((len(l),)+l[0].shape) 
for i, v in enumerate(l):
   arr[i] = v
Run Code Online (Sandbox Code Playgroud)

对我来说工作得更快,它只需要一个内存分配


hpa*_*ulj 6

这取决于New_Rows[i]你想要什么 ,以及你想要什么样的阵列.如果你从列表(或1d数组)开始,你想要端到端地连接(做一个长的1d数组),只需将它们连接起来.Concatenate采用任何长度的列表,而不仅仅是2个项目.

 np.concatenate(New_Rows, axis=0)
Run Code Online (Sandbox Code Playgroud)

或者可以使用中间列表理解(为了更大的灵活性)

 np.concatenate([row for row in New_Rows])
Run Code Online (Sandbox Code Playgroud)

或者更接近你的例子.

 np.concatenate([New_Rows[i] for i in range(1000)])
Run Code Online (Sandbox Code Playgroud)

但是如果New_Rows元素的长度都相同,并且你想要一个2d数组,New_Rows每行一个值,np.array那么做得很好:

 np.array(New_Rows)
 np.array([i for i in New_Rows])
 np.array([New_Rows[i] for i in range(1000)])
Run Code Online (Sandbox Code Playgroud)

np.array 主要用于从列表列表构建数组.

np.concatenate也可以在2d内构建,但输入需要以2d开头. vstack并且stack可以照顾到这一点.但是所有这些stack函数都使用了某种列表理解concatenate.

通常,迭代或附加列表更好/更快,并且只应用np.array(或连接)一次. appending列表很快; 比制作​​新阵列要快得多.