2015-06-11 3 views
5

In Matlab, posso effettuare le seguenti operazioni:Un modo semplice per comprimere le dimensioni finali di array numpy?

X = randn(25,25,25); 
size(X(:,:)) 

ans = 
    25 625 

Spesso mi trovo a voler crollare rapidamente le dimensioni finali di una matrice, e non so come fare questo in NumPy.

So che posso fare questo:

In [22]: x = np.random.randn(25,25,25) 
In [23]: x = x.reshape(x.shape[:-2] + (-1,)) 
In [24]: x.shape 
Out[24]: (25, 625) 

ma x.reshape(x.shape[:-2] + (-1,)) è un molto meno conciso (e richiede ulteriori informazioni su x) che semplicemente facendo x(:,:).

Sono ovviamente provato l'indicizzazione NumPy analoga, ma che non funziona come desiderato:

In [25]: x = np.random.randn(25,25,25) 
In [26]: x[:,:].shape 
Out[26]: (25, 25, 25) 

Eventuali suggerimenti su come comprimere le dimensioni finali di un array in maniera concisa?

Modifica: si noti che sto cercando la matrice risultante, non solo la sua forma. Io uso semplicemente size() e x.shape negli esempi precedenti per indicare come è la matrice.

+0

Su una nota a margine, l'esempio non è corretto ... 'x.shape [: - 2]' restituirebbe una tupla vuota. (Aggiungendo '-1' a questo significa che la matrice verrebbe" appiattita "in una matrice di 15625 lunghezze.) Immagino che tu intenda" x.shape [0] '? –

+0

@JoeKington: È * corretto * (provalo). 'x.shape [: - 2]' restituisce 'x.shape' fino a (ma non incluso) il penultimo elemento. Quindi per un array 3D 'x', restituisce solo il primo elemento di' x.shape'. Ho usato '[: -2]' piuttosto che '[0]' perché sto cercando una soluzione generale che funzioni per tutti gli array ND in cui N> 2. – EelkeSpaak

+0

@ElkeSpaak - Giusto. Non stavo pensando chiaramente. –

risposta

3

Cosa dovrebbe accadere con un 4d o superiore?

octave:7> x=randn(25,25,25,25); 
octave:8> size(x(:,:)) 
ans = 
     25 15625 

tuo (:,:) riduce a 2 dimensioni, combinando gli ultimi. L'ultima dimensione è dove MATLAB aggiunge e collassa automaticamente le dimensioni.

In [605]: x=np.ones((25,25,25,25)) 

In [606]: x.reshape(x.shape[0],-1).shape # like Joe's 
Out[606]: (25, 15625) 

In [607]: x.reshape(x.shape[:-2]+(-1,)).shape 
Out[607]: (25, 25, 625) 

tuo reshape esempio fa qualcosa di diverso da MATLAB, semplicemente crolla l'ultimo 2. Crollare giù a 2 dimensioni come MATLAB è un'espressione più semplice.

Il MATLAB è conciso semplicemente perché le vostre esigenze corrispondono alle sue ipotesi. Il numpy equivalente non è così conciso, ma ti dà più controllo

Ad esempio per mantenere l'ultima dimensione, o combinare le dimensioni 2 per 2:

In [608]: x.reshape(-1,x.shape[-1]).shape 
Out[608]: (15625, 25) 
In [610]: x.reshape(-1,np.prod(x.shape[-2:])).shape 
Out[610]: (625, 625) 

Qual è l'equivalente MATLAB?

octave:24> size(reshape(x,[],size(x)(2:end))) 
ans = 
15625  25 
octave:31> size(reshape(x,[],prod(size(x)(3:end)))) 
1

È possibile utilizzare np.hstack:

>>> np.hstack(x).shape 
(25, 625) 

np.hstack ake una sequenza di matrici e impilarli orizzontalmente per fare una singola matrice.

+1

Questo è un uso interessante di 'np.hstack'! Tuttavia, non produce lo stesso risultato di 'x.reshape (x.shape [: - 2] + (-1,))', quindi dovrebbe essere usato con cautela. Pensandoci un po 'oltre, quello che credo stia succedendo è che 'np.hstack' tratta la * prima * dimensione dell'array come dimensione iterabile, e quindi restituisce lo stesso di' np.hstack (x [0 ,: ,:], x [1,:,:], ...) '. Ho bisogno di funzionalità che lasciano intoccata la prima dimensione (cioè tutti i dati precedentemente in x [0,:,:] sono ora in x [0 ,:]), come nel caso della versione Matlab. – EelkeSpaak

+0

Vuoi un nuovo array o vuoi solo la sua forma? – Kasramvd

+0

Sto cercando il contenuto della matrice stessa, la forma è solo per illustrazione. Ho modificato la domanda originale per renderlo più chiaro. – EelkeSpaak

1

Si potrebbe trovare un po 'più conciso modificare direttamente l'attributo shape. Ad esempio:

import numpy as np 

x = np.random.randn(25, 25, 25) 
x.shape = x.shape[0], -1 

print x.shape 
print x 

Questo è funzionalmente equivalente al reshape (nel senso di ordinamento dei dati, ecc). Ovviamente, richiede ancora le stesse informazioni sulla forma di x, ma è un modo più conciso di gestire la risagoma.

+1

Ha aggiunto il "vantaggio" che, se la risagoma non può essere eseguita senza una copia, genererà un errore, quindi lo uso spesso come una forma per affermare che il mio codice utilizza in modo efficiente la memoria. – Jaime