Подтвердить что ты не робот

Как расширить массив на месте в Numpy?

В настоящее время у меня есть код вроде этого

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-in-place

Мне было интересно, могу ли я использовать 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 будет намного более эффективным. У кого-нибудь есть идеи об этом? Спасибо!

4b9b3361

Ответ 1

Представьте, что массив numpy занимает один непрерывный блок памяти. Теперь представьте другие объекты, скажем, другие массивы numpy, которые занимают память только слева и справа от нашего массива numpy. Не было бы места для добавления или расширения нашего массива numpy. Базовые данные в массиве numpy всегда занимают непрерывный блок памяти.

Таким образом, любой запрос на добавление или расширение нашего массива numpy может быть удовлетворен только путем выделения целого нового большего блока памяти, копирования старых данных в новый блок, а затем добавления или расширения.

Итак:

  • Это не произойдет на месте.
  • Это не будет эффективно.

Ответ 2

Вы можете использовать метод ntarrays .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

Эффективность может быть улучшена за счет использования обычных схем перераспределения памяти массива.

Ответ 3

Обычный способ справиться с этим выглядит примерно так:

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)

По причинам, связанным с другими ответами, вообще невозможно расширить массив без копирования данных.