Come convertire l'elenco di array numpy in un singolo array numpy?


103

Supponiamo di averlo fatto;

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

Provo a convertire;

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

Lo sto risolvendo per iterazione su vstack in questo momento, ma è molto lento per LIST particolarmente grandi

Cosa suggerisci per il modo più efficiente?


5
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])]questa non è la sintassi Python corretta. Si prega di precisare.
Marcin

Risposte:


131

In generale puoi concatenare un'intera sequenza di array lungo qualsiasi asse:

numpy.concatenate( LIST, axis=0 )

ma non ci si deve preoccupare circa la forma e la dimensionalità di ogni matrice della lista (per un'uscita 3x5 2-dimensionale, è necessario garantire che essi siano tutti 2-dimensionali array N-per-5 già). Se si desidera concatenare array unidimensionali come righe di un output bidimensionale, è necessario espandere la loro dimensionalità.

Come sottolinea la risposta di Jorge, c'è anche la funzione stack, introdotta in numpy 1.10:

numpy.stack( LIST, axis=0 )

Questo adotta l'approccio complementare: crea una nuova vista di ogni array di input e aggiunge una dimensione extra (in questo caso, a sinistra, quindi ogni narray 1D -element diventa un array 1-by- n2D) prima della concatenazione. Funzionerà solo se tutti gli array di input hanno la stessa forma, anche lungo l'asse di concatenazione.

vstack(o equivalentemente row_stack) è spesso una soluzione più facile da usare perché richiederà una sequenza di array a 1 e / o 2 dimensioni ed espanderà la dimensionalità automaticamente dove necessario e solo dove necessario, prima di concatenare l'intero elenco insieme. Dove è richiesta una nuova dimensione, viene aggiunta a sinistra. Ancora una volta, puoi concatenare un intero elenco in una volta senza bisogno di iterare:

numpy.vstack( LIST )

Questo comportamento flessibile è anche esibito dalla scorciatoia sintattica numpy.r_[ array1, ...., arrayN ](notare le parentesi quadre). Questo è utile per concatenare alcuni array con nomi espliciti, ma non va bene per la tua situazione perché questa sintassi non accetterà una sequenza di array, come il tuo LIST.

Esiste anche una funzione column_stacke una scorciatoia analoghe c_[...], per lo stacking orizzontale (a colonna), nonché una funzione quasi analoga, hstacksebbene per qualche motivo quest'ultima sia meno flessibile (è più rigorosa sulla dimensionalità degli array di input e cerca di concatenare Array 1-D end-to-end invece di trattarli come colonne).

Infine, nel caso specifico di stacking verticale di array 1-D, funziona anche quanto segue:

numpy.array( LIST )

... perché gli array possono essere costruiti da una sequenza di altri array, aggiungendo una nuova dimensione all'inizio.


5
Penso che volesse un array 2d come output.
Beefster

7

A partire dalla versione 1.10 di NumPy, abbiamo lo stack dei metodi . Può impilare array di qualsiasi dimensione (tutti uguali):

# 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

Godere,


1

Ho controllato alcuni metodi per le prestazioni di velocità e ho scoperto che non c'è differenza! L'unica differenza è che utilizzando alcuni metodi è necessario controllare attentamente la dimensione.

Tempistica:

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

Come puoi vedere ho provato 2 esperimenti - usando np.random.rand(10000)e np.random.rand(1, 10000) E se usiamo array 2d np.stacke np.arraycreiamo una dimensione aggiuntiva - result.shape è (1,10000,10000) e (10000,1,10000) quindi hanno bisogno di azioni aggiuntive per evitarlo .

Codice:

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}')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.