Wie konvertiere ich eine Liste von Numpy-Arrays in ein einzelnes Numpy-Array?

100

Angenommen, ich habe;

LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])] # inner lists are numpy arrays

Ich versuche zu konvertieren;

array([[1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5])

Ich löse es gerade durch Iteration auf vstack, aber es ist sehr langsam für besonders große LIST

Was schlagen Sie für den effizientesten Weg vor?

erogol
quelle
5
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])]Dies ist keine korrekte Python-Syntax. Bitte klären Sie.
Marcin

Antworten:

127

Im Allgemeinen können Sie eine ganze Folge von Arrays entlang einer beliebigen Achse verketten:

numpy.concatenate( LIST, axis=0 )

aber Sie tun müssen , um Sorgen über die Form und Dimensionalität jeder Anordnung in der Liste (für einen 2-dimensionalen 3x5 - Ausgang, müssen Sie sicherstellen , dass sie alle sind 2-dimensionaler n-by-5 - Arrays bereits). Wenn Sie eindimensionale Arrays als Zeilen einer zweidimensionalen Ausgabe verketten möchten, müssen Sie deren Dimensionalität erweitern.

Wie Jorges Antwort zeigt, gibt es auch die Funktion stack, die in Numpy 1.10 eingeführt wurde:

numpy.stack( LIST, axis=0 )

Dies erfolgt nach dem komplementären Ansatz: Es wird eine neue Ansicht jedes Eingabearrays erstellt und vor dem Verketten eine zusätzliche Dimension nhinzugefügt (in diesem Fall links, sodass jedes Element-1D-Array zu einem 1-mal- n2D-Array wird). Dies funktioniert nur, wenn alle Eingabearrays dieselbe Form haben - auch entlang der Verkettungsachse.

vstack(oder gleichwertig row_stack) ist häufig eine benutzerfreundlichere Lösung, da eine Folge von 1- und / oder 2-dimensionalen Arrays verwendet wird und die Dimensionalität bei Bedarf und nur bei Bedarf automatisch erweitert wird, bevor die gesamte Liste zusammengefügt wird. Wenn eine neue Dimension erforderlich ist, wird sie links hinzugefügt. Auch hier können Sie eine ganze Liste auf einmal verketten, ohne sie wiederholen zu müssen:

numpy.vstack( LIST )

Dieses flexible Verhalten zeigt auch die syntaktische Verknüpfung numpy.r_[ array1, ...., arrayN ](beachten Sie die eckigen Klammern). Dies ist gut für die Verkettung einiger explizit benannter Arrays, aber nicht gut für Ihre Situation, da diese Syntax keine Folge von Arrays wie Ihre akzeptiert LIST.

Es gibt auch eine analoge Funktion column_stackund Verknüpfung c_[...]für das horizontale (spaltenweise) Stapeln sowie eine fast analoge Funktion - hstackobwohl letztere aus irgendeinem Grund weniger flexibel ist (sie ist strenger in Bezug auf die Dimensionalität der Eingabearrays und versucht zu verketten 1-D-Arrays Ende-zu-Ende, anstatt sie als Spalten zu behandeln).

Schließlich funktioniert im speziellen Fall des vertikalen Stapelns von 1-D-Arrays auch Folgendes:

numpy.array( LIST )

... weil Arrays aus einer Folge anderer Arrays erstellt werden können und dem Anfang eine neue Dimension hinzugefügt wird.

jez
quelle
5
Ich denke, er wollte ein 2D-Array als Ausgabe.
Beefster
7

Ab NumPy Version 1.10 haben wir die Methode Stapel . Es kann Arrays jeder Dimension stapeln (alle gleich):

# List of arrays.
L = [np.random.randn(5,4,2,5,1,2) for i in range(10)]

# Stack them using axis=0.
M = np.stack(L)
M.shape # == (10,5,4,2,5,1,2)
np.all(M == L) # == True

M = np.stack(L, axis=1)
M.shape # == (5,10,4,2,5,1,2)
np.all(M == L) # == False (Don't Panic)

# This are all true    
np.all(M[:,0,:] == L[0]) # == True
all(np.all(M[:,i,:] == L[i]) for i in range(10)) # == True

Genießen,

Jorge E. Cardona
quelle
1

Ich habe einige Methoden auf Geschwindigkeitsleistung überprüft und festgestellt, dass es keinen Unterschied gibt! Der einzige Unterschied besteht darin, dass Sie mit einigen Methoden die Dimension sorgfältig prüfen müssen.

Zeitliche Koordinierung:

|------------|----------------|-------------------|
|            | shape (10000)  |  shape (1,10000)  |
|------------|----------------|-------------------|
| np.concat  |    0.18280     |      0.17960      |
|------------|----------------|-------------------|
|  np.stack  |    0.21501     |      0.16465      |
|------------|----------------|-------------------|
| np.vstack  |    0.21501     |      0.17181      |
|------------|----------------|-------------------|
|  np.array  |    0.21656     |      0.16833      |
|------------|----------------|-------------------|

Wie Sie sehen können, habe ich zwei Experimente versucht - mit np.random.rand(10000)und np.random.rand(1, 10000) Und wenn wir 2D-Arrays als verwenden np.stackund np.arrayeine zusätzliche Dimension erstellen - result.shape ist (1.10000.10000) und (10000, 1.10000), daher benötigen sie zusätzliche Aktionen, um dies zu vermeiden .

Code:

from time import perf_counter
from tqdm import tqdm_notebook
import numpy as np
l = []
for i in tqdm_notebook(range(10000)):
    new_np = np.random.rand(10000)
    l.append(new_np)



start = perf_counter()
stack = np.stack(l, axis=0 )
print(f'np.stack: {perf_counter() - start:.5f}')

start = perf_counter()
vstack = np.vstack(l)
print(f'np.vstack: {perf_counter() - start:.5f}')

start = perf_counter()
wrap = np.array(l)
print(f'np.array: {perf_counter() - start:.5f}')

start = perf_counter()
l = [el.reshape(1,-1) for el in l]
conc = np.concatenate(l, axis=0 )
print(f'np.concatenate: {perf_counter() - start:.5f}')
Mikhail_Sam
quelle