web-dev-qa-db-fra.com

Comment étendre un tableau sur place dans Numpy?

Actuellement, j'ai un code comme celui-ci

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))

Je pense que ce code est pas efficace comme np.append doit retourner une copie du tableau au lieu de modifier le ret sur place

Je me demandais si je pouvais utiliser le extend pour un tableau numpy comme celui-ci:

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))

Pour que le extend soit beaucoup plus efficace. Quelqu'un a-t-il des idées à ce sujet? Merci!

26
Hanfei Sun

Imaginez un tableau numpy occupant un bloc de mémoire contigu. Imaginez maintenant d'autres objets, par exemple d'autres tableaux numpy, qui occupent la mémoire juste à gauche et à droite de notre tableau numpy. Il n'y aurait pas de place pour ajouter ou étendre notre tableau numpy. Les données sous-jacentes d'un tableau numpy occupent toujours un bloc de mémoire contig.

Ainsi, toute demande d'ajout ou d'extension à notre tableau numpy ne peut être satisfaite qu'en allouant un tout nouveau bloc de mémoire plus grand, en copiant les anciennes données dans le nouveau bloc, puis en ajoutant ou en étendant.

Donc:

  1. Cela ne se produira pas sur place.
  2. Ce ne sera pas efficace.
32
unutbu

Vous pouvez utiliser la méthode .resize() des ndarrays. Cela nécessite que la mémoire ne soit pas référencée par d'autres tableaux/variables.

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

L'efficacité peut être améliorée en utilisant les schémas de surallocation de mémoire de tableau habituels.

12
pv.

La façon habituelle de gérer cela est quelque chose comme ceci:

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)

Pour des raisons dans lesquelles d'autres réponses sont entrées, il est généralement impossible d'étendre un tableau sans copier les données.

10
Bi Rico

Je suis tombé sur cette question en recherchant des méthodes d'insertion numpy sur place.

En lisant les réponses qui ont été données ici, il m'est apparu une alternative (peut-être naïve, mais toujours une idée): pourquoi ne pas reconvertir le tableau numpy en liste, ajouter tout ce que vous voulez y ajouter et le reconvertir retour à un tableau?

Dans le cas où vous devez effectuer de nombreuses insertions, vous pouvez créer une sorte de "cache de liste" où vous mettriez toutes les insertions et les inséreriez dans la liste en une seule étape.

Bien sûr, si l'on essaie d'éviter à tout prix une conversion en liste et de nouveau en numpy, ce n'est pas une option.

0