如何在Numpy中就地扩展数组?

时间:2012-11-04 02:35:45

标签: python arrays numpy scipy

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

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需要返回数组的副本而不是修改就地

我想知道我是否可以将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 个答案:

答案 0 :(得分:29)

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

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

所以:

  1. 不会就地发生。
  2. 效率不高。

答案 1 :(得分:12)

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

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

使用通常的阵列存储器叠加方案可以提高效率。

答案 2 :(得分:10)

处理此问题的常用方法是这样的:

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)

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

答案 3 :(得分:0)

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

在阅读这里给出的答案时,我想到了另一种选择(也许是一个幼稚的想法,但仍然是一个主意):为什么不将numpy数组转换回列表,将想要添加的内容追加到列表中并将其转换回数组?

如果您需要完成许多插入操作,则可以创建一种“列表缓存”,在其中将所有插入内容放入并一步插入到列表中。

当然,如果要不惜一切代价避免转换为列表然后再返回为numpy,则不是一种选择。