60

目前,我有一些这样的代码

import numpy as np
ret = np.array([])
for i in range(100000):
  tmp =  get_input(i)
  ret = np.append(ret, np.zeros(len(tmp)))
  ret = np.append(ret, np.ones(fixed_length))

我认为这段代码效率不高,因为np.append需要返回数组的副本而不是就地修改 ret

我想知道我是否可以extend像这样使用 numpy 数组:

import numpy as np
from somewhere import np_extend
ret = np.array([])
for i in range(100000):
  tmp =  get_input(i)
  np_extend(ret, np.zeros(len(tmp)))
  np_extend(ret, np.ones(fixed_length))

这样extend会更有效率。有人对此有想法吗?谢谢!

4

4 回答 4

68

想象一个 numpy 数组占用一个连续的内存块。现在想象一下其他对象,比如其他 numpy 数组,它们占用了我们 numpy 数组左右两侧的内存。没有空间可以附加或扩展我们的 numpy 数组。numpy 数组中的底层数据总是占用一个连续的内存块。

因此,任何附加或扩展我们的 numpy 数组的请求只能通过分配一个全新的更大内存块、将旧数据复制到新块然后附加或扩展来满足。

所以:

  1. 它不会就地发生。
  2. 它不会是有效的。
于 2012-11-04T02:43:10.230 回答
20

您可以使用.resize()ndarrays 的方法。它要求内存不被其他数组/变量引用。

import numpy as np
ret = np.array([])
for i in range(100):
    tmp = np.random.rand(np.random.randint(1, 100))
    ret.resize(len(ret) + len(tmp)) # <- ret is not referred to by anything else,
                                    #    so this works
    ret[-len(tmp):] = tmp

可以通过使用通常的数组内存过度分配方案来提高效率。

于 2012-11-04T03:01:30.313 回答
16

通常的处理方法是这样的:

import numpy as np
ret = []
for i in range(100000):
  tmp =  get_input(i)
  ret.append(np.zeros(len(tmp)))
  ret.append(np.zeros(fixed_length))
ret = np.concatenate(ret)

由于其他答案的原因,通常不可能在不复制数据的情况下扩展数组。

于 2012-11-04T17:13:11.283 回答
1

我在研究就地 numpy 插入方法时遇到了这个问题。

在阅读此处给出的答案时,我想到了一个替代方案(可能是一个幼稚的想法,但仍然是一个想法):为什么不将 numpy 数组转换回列表,附加任何你想附加的内容并重新转换它回到数组?

如果您必须完成许多插入操作,您可以创建一种“列表缓存”,您可以在其中放置所有插入,然后一步将它们插入到列表中。

当然,如果有人试图不惜一切代价避免转换为列表并返回到 numpy,这不是一种选择。

于 2019-03-09T15:54:36.723 回答