Hoe kan ik een array op zijn plaats uitbreiden in Numpy?

Momenteel heb ik een code zoals deze

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

Ik denk dat deze code niet efficiëntis omdat np.appendeen kopie van de array moet retourneren in plaats van de ret in-place aan te passen

Ik vroeg me af of ik de extendkan gebruiken voor een numpy array zoals deze:

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

Zodat de extendveel efficiënter zou zijn.
Heeft iemand hier ideeën over?
Bedankt!


Antwoord 1, autoriteit 100%

Stel je een numpy array voor als een aaneengesloten geheugenblok. Stel je nu andere objecten voor, zeg andere numpy-arrays, die het geheugen net links en rechts van onze numpy-array in beslag nemen. Er zou geen ruimte zijn om onze numpy array toe te voegen of uit te breiden. De onderliggende gegevens in een numpy-array nemen altijd een aangrenzendgeheugenblok in beslag.

Dus elk verzoek om onze numpy-array toe te voegen of uit te breiden, kan alleen worden ingewilligd door een geheel nieuw groter geheugenblok toe te wijzen, de oude gegevens naar het nieuwe blok te kopiëren en vervolgens toe te voegen of uit te breiden.

Dus:

  1. Het zal niet ter plaatse gebeuren.
  2. Het zal niet efficiënt zijn.

Antwoord 2, autoriteit 28%

Je kunt de .resize()methode van ndarrays gebruiken. Het vereist dat er niet naar het geheugen wordt verwezen door andere arrays/variabelen.

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

De efficiëntie kan worden verbeterd door gebruik te maken van de gebruikelijke schema’s voor oververdeling van het array-geheugen.


Antwoord 3, autoriteit 18%

De gebruikelijke manier om dit aan te pakken is ongeveer als volgt:

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)

Om redenen waar andere antwoorden op zijn ingegaan, is het over het algemeen onmogelijk om een array uit te breiden zonder de gegevens te kopiëren.


Antwoord 4, autoriteit 2%

Ik kwam deze vraag tegen toen ik onderzoek deed naar inplace numpy-inbrengmethoden.

Tijdens het lezen van de antwoorden die hier zijn gegeven, bedacht ik me een alternatief (misschien een naïeve, maar toch een idee): waarom zet je de numpy-array niet terug in een lijst, voeg je eraan toe wat je eraan wilt toevoegen en weer terug naar een array converteren?

Als u te veel invoegingen moet doen, kunt u een soort “lijstcache” maken waarin u alle invoegingen in één stap in de lijst plaatst.

Als men koste wat kost een conversie naar een lijst en terug naar een numpy probeert te vermijden, is dit natuurlijk geen optie.

Other episodes