高效的numpy数组追加方法

6 投票
3 回答
19529 浏览
提问于 2025-04-18 11:15

我会尽量简单明了。我有一个循环,它会往一个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 个回答

0

你可以试试:

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 在循环中不需要被访问的话,我会选择用一个列表。

6

如果你已经把所有东西放在一个列表里,有三种方法可以做到这一点:

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)) 来开始,但我不建议在循环中往那个数组里添加数据。

10

这里简单解释一下“为什么使用列表”的部分。

内部来说,列表的长度不确定的问题在于,无论它的长度是多少,都需要在内存中找到一个地方来存放它。基本上有两种不同的解决方法:

  1. 使用一种数据结构(比如链表、某种树结构等),这样可以为列表中的每个新元素单独分配内存。

  2. 把数据存储在一个连续的内存区域。这块区域在创建列表时就要分配好,并且要比我们最开始需要的空间大。如果我们往列表里添加更多内容,就需要尝试再分配更多的内存,最好是在同一个地方。如果不能在同一个地方分配,就得分配一个更大的内存块,并把所有数据移动过去。

第一种方法可以实现各种复杂的插入、删除、排序等操作,但在顺序读取时会比较慢,并且会占用更多内存。实际上,Python使用的是第二种方法,列表被存储为“动态数组”。想了解更多,可以查看:

内存中列表的大小

这意味着列表在使用append时非常高效。如果你事先不知道列表的大小,几乎没有什么方法可以加快速度。


如果你事先知道列表的最大大小,最好使用numpy.empty(而不是numpy.zeros)来分配一个最大大小的numpy.array,然后在填充完所有数据后,使用ndarray.resize来缩小数组。

出于某种原因,numpy.array(l)(其中l是一个列表)在处理大列表时通常会比较慢,而复制即使是很大的数组却相当快(我刚试着创建一个包含1亿个元素的数组,花了不到0.5秒)。

这个讨论中有关于不同选项的更多基准测试:

扩展numpy数值数组的最快方法

我没有对numpy.emptyndarray.resize的组合进行基准测试,但这两者的操作应该是微秒级别,而不是毫秒级别。

撰写回答