高效的numpy数组追加方法
我会尽量简单明了。我有一个循环,它会往一个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])
更糟糕的是,这样会产生一个未初始化的值。
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
在循环中不需要被访问的话,我会选择用一个列表。
如果你已经把所有东西放在一个列表里,有三种方法可以做到这一点:
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))
来开始,但我不建议在循环中往那个数组里添加数据。
这里简单解释一下“为什么使用列表”的部分。
内部来说,列表的长度不确定的问题在于,无论它的长度是多少,都需要在内存中找到一个地方来存放它。基本上有两种不同的解决方法:
使用一种数据结构(比如链表、某种树结构等),这样可以为列表中的每个新元素单独分配内存。
把数据存储在一个连续的内存区域。这块区域在创建列表时就要分配好,并且要比我们最开始需要的空间大。如果我们往列表里添加更多内容,就需要尝试再分配更多的内存,最好是在同一个地方。如果不能在同一个地方分配,就得分配一个更大的内存块,并把所有数据移动过去。
第一种方法可以实现各种复杂的插入、删除、排序等操作,但在顺序读取时会比较慢,并且会占用更多内存。实际上,Python使用的是第二种方法,列表被存储为“动态数组”。想了解更多,可以查看:
这意味着列表在使用append
时非常高效。如果你事先不知道列表的大小,几乎没有什么方法可以加快速度。
如果你事先知道列表的最大大小,最好使用numpy.empty
(而不是numpy.zeros
)来分配一个最大大小的numpy.array
,然后在填充完所有数据后,使用ndarray.resize
来缩小数组。
出于某种原因,numpy.array(l)
(其中l
是一个列表)在处理大列表时通常会比较慢,而复制即使是很大的数组却相当快(我刚试着创建一个包含1亿个元素的数组,花了不到0.5秒)。
这个讨论中有关于不同选项的更多基准测试:
我没有对numpy.empty
和ndarray.resize
的组合进行基准测试,但这两者的操作应该是微秒级别,而不是毫秒级别。