我正在运行以下代码:
for i in range(1000)
My_Array=numpy.concatenate((My_Array,New_Rows[i]), axis=0)
上面的代码很慢。有没有更快的方法?
答案 0 :(得分:14)
这基本上是基于数组的所有算法中发生的事情。
每次更改数组的大小时,都需要调整大小,并且需要复制每个元素。这也发生在这里。 (一些实现保留了一些空槽;例如,随着每个增长,内部存储器的空间加倍)。
这不是一个特定于numpy的主题,而是关于数据结构的更多内容。
编辑,因为这个相当含糊的答案得到了一些赞成,我觉得有必要明确我的链表方法就是一个可能的例子。正如评论中所指出的,python的列表更像数组(绝对不是链表)。但核心事实是:python中的list.append()是fast(摊销:O(1)),而numpy-arrays则不然!关于docs中的内部构件还有一小部分:
如何实施清单?
Python的列表实际上是可变长度的数组,而不是Lisp样式的链表。 实现使用对其他对象的连续引用数组,并在列表头结构中保留指向此数组和数组长度的指针。
这使得列表a [i]为索引编制索引,其成本与列表大小或索引值无关。
添加或插入项目时,将调整引用数组的大小。 应用一些聪明才能提高重复附加项目的效果;当必须增长数组时,会分配一些额外的空间,因此接下来的几次不需要实际调整大小。
(我的加粗注释)
答案 1 :(得分:6)
这取决于New_Rows[i]
是什么,以及你想要什么样的数组。如果你从列表(或1d数组)开始,你想要端到端地连接(做一个长的1d数组),只需将它们连接起来。 Concatenate获取任何长度的列表,而不仅仅是2个项目。
np.concatenate(New_Rows, axis=0)
或者可能使用中间列表理解(为了更大的灵活性)
np.concatenate([row for row in New_Rows])
或更接近你的例子。
np.concatenate([New_Rows[i] for i in range(1000)])
但如果New_Rows
元素的长度相同,并且您想要一个二维数组,每行一个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)])
np.array
主要用于从列表列表构建数组。
np.concatenate
也可以在2d中构建,但输入需要以2d开头。 vstack
和stack
可以照顾到这一点。但是所有这些stack
函数都使用某种列表推导,然后是concatenate
。
通常,迭代或附加列表会更好/更快,并且只应用np.array
(或连接)一次。 appending
列表很快;比制作新阵列要快得多。
答案 2 :(得分:0)
也许创建一个具有正确大小的空数组,然后填充它? 如果您具有相同尺寸的数组列表,则可以
import numpy as np
arr = np.zeros((len(l),)+l[0].shape)
for i, v in enumerate(l):
arr[i] = v
对我来说工作快得多,只需要分配一个内存
答案 3 :(得分:0)
我认为@thebeancounter的解决方案是解决之道。 如果您事先不知道numpy数组的确切大小,也可以采用类似于在C ++中实现矢量类的方法。
更具体地说,您可以将numpy ndarray包装到一个新的类中,该类的默认大小大于您当前的需要。当numpy数组几乎完全填充后,将当前数组复制到更大的数组。
答案 4 :(得分:-1)
假设您有大量的2D numpy数组,具有相同的列数和不同的行数:
x = [numpy_array1(r_1,c),......,numpy_arrayN(r_n,c)]
像这样串联:
while len(x) != 1:
if len(x) == 2:
x = np.concatenate((x[0], x[1]))
break
for i in range(0, len(x), 2):
if (i+1) == len(x):
x[0] = np.concatenate((x[0], x[i]))
else:
x[i] = np.concatenate((x[i], x[i+1]))
x = x[::2]