附加numpy数组的有效方法
Posted
技术标签:
【中文标题】附加numpy数组的有效方法【英文标题】:Efficient way for appending numpy array 【发布时间】:2014-06-26 19:56:48 【问题描述】:我会保持简单。我有一个循环,将新行附加到一个 numpy 数组...什么是执行此操作的有效方法。
n=np.zeros([1,2])
for x in [[2,3],[4,5],[7,6]]
n=np.append(n,x,axis=1)
现在问题是有一个 [0,0] 粘在上面,所以我必须通过
将其删除 del n[0]
这似乎很愚蠢......所以请告诉我一个有效的方法来做到这一点。
n=np.empty([1,2])
更糟糕的是它会创建一个未初始化的值。
【问题讨论】:
你为什么不直接做n = np.array([[2,3],[4,5],[7,6]])
?
这只是一个例子,在我的程序中每次迭代都会附加一个不同的值
附加到 numpy 数组本质上是低效的,所以这种方法在性能方面永远不会很好。
如果n
是一个numpy 数组,我相信del n[0]
会报错。
追加到列表中并从该列表列表构建数组会更有效。追加到数组效率不高。
【参考方案1】:
“为什么列表”部分的一些技术解释。
在内部,未知长度列表的问题在于它需要以某种方式适应内存,而不管其长度如何。基本上有两种不同的可能性:
使用数据结构(链表、一些树结构等),可以为列表中的每个新元素单独分配内存。
将数据存储在连续的内存区域中。该区域必须在创建列表时分配,并且必须大于我们最初需要的区域。如果我们将更多的东西放入列表中,我们需要尝试分配更多的内存,最好是在同一位置。如果我们不能在同一个位置做,我们需要分配一个更大的块并移动所有数据。
第一种方法可以实现各种花哨的插入和删除选项、排序等。但是,它在顺序读取方面速度较慢,并且分配的内存更多。 Python实际上使用方法#2,列表存储为“动态数组”。有关这方面的更多信息,请参阅:
Size of list in memory
这意味着列表被设计为使用append
非常有效。如果您事先不知道列表的大小,那么您几乎无法加快速度。
如果您事先知道列表的最大大小,您可能最好使用具有最大大小的numpy.empty
(不是numpy.zeros
)分配numpy.array
,然后使用ndarray.resize
将数组缩小一次您已填写所有数据。
由于某种原因numpy.array(l)
其中l
是一个列表,对于大型列表来说通常很慢,而复制即使是大型数组也相当快(我只是尝试创建一个 100 000 000 个元素数组的副本;它花费的时间更少小于 0.5 秒)。
本次讨论对不同选项进行了更多基准测试:
Fastest way to grow a numpy numeric array
我还没有对 numpy.empty
+ ndarray.resize
组合进行基准测试,但两者都应该是微秒而不是毫秒。
【讨论】:
一个python列表是同时使用(1)和(2),因为每个对象都有自己的分配,列表元素只是对它的引用。与numpy记录数组相比,其中每条记录都内联存储在数组中,紧凑地使用 (2) 策略。使它们与众不同的是它们的分配策略。该列表将分配额外的容量。 (1) 因素确保列表中的每个插槽本身都非常小,因此未使用的容量不会花费那么多。 我发现至少在我的案例中最好的解决方案之一是预先分配足够大的空间,然后更改它并移动自定义“长度”变量。需要更多的工作,但性能是值得的。【参考方案2】:如果您已经将所有内容都放在列表中,则可以使用三种方法:
data = [[2, 3], [4, 5], [7, 6]]
n = np.array(data)
如果你知道最终的数组有多大:
exp = np.array([2, 3])
n = np.empty((3, 2))
for i in range(3):
n[i, :] = i ** exp
如果你不知道最终的数组有多大:
exp = np.array([2, 3])
n = []
i = np.random.random()
while i < .9:
n.append(i ** exp)
i = np.random.random()
n = np.array(n)
您可以以 n = np.empty((0, 2))
开头的记录或记录,但我不建议在循环中附加到该数组。
【讨论】:
所有方法都使用列表......难道没有办法在 np.arrays 中完全做到这一点...... numpy 的家伙难道不能想出办法吗?而 'n=np.empty((0,2))' 不起作用 我 100% 保证n = np.empty((0, 2))
有效。你不必使用列表,但你必须使用一些东西。您的数据不能凭空而来,它必须在放入数组之前具有某种结构(即,文件、另一个数组、列表、元组、双精度...)。
同样在第三种情况下,当你不知道数组的最终大小时,我故意使用了一个列表。 python 列表实际上是作为dynamic array 实现的,这是您在最后一种情况下想要的。 Numpy 数组不是动态数组,因此最好使用列表。【参考方案3】:
你可能想试试:
import numpy as np
n = np.reshape([], (0, 2))
for x in [[2,3],[4,5],[7,6]]:
n = np.append(n, [x], axis=0)
除了np.append
,您还可以使用n = np.vstack([n,x])
。我也同意@Bi Rico 的观点,如果n
不需要在循环内访问,我也会使用列表。
【讨论】:
以上是关于附加numpy数组的有效方法的主要内容,如果未能解决你的问题,请参考以下文章