2016-03-15 16 views
9

In numpy le dimensioni dell'array risultante variano in fase di esecuzione. C'è spesso confusione tra un array 1d e un array 2d con 1 colonna. In un caso posso scorrere le colonne, nell'altro caso non posso.Numpy rimodella l'array da 1d a 2d con 1 colonna

Come risolvete elegantemente questo problema? Per evitare riempire il programma if dichiarazioni il controllo per la dimensionalità, io uso questa funzione:

def reshape_to_vect(ar): 
    if len(ar.shape) == 1: 
     return ar.reshape(ar.shape[0],1) 
    return ar 

Tuttavia, questo si sente poco elegante e costoso. C'è una soluzione migliore?

+0

Che cos'è il 'dtype'? Sembra 'strutturato'. – hpaulj

+0

È irrilevante, l'ho usato solo come esempio di come potrei finire con un array 1d o 2d. La mia domanda riguarda come convertire sistematicamente l'array da 1d a 2d in modo sistematico. – DevShark

risposta

7

si potrebbe fare -

ar.reshape(ar.shape[0],-1) 

Questo secondo ingresso al reshape: -1 si occupa del numero di elementi per il secondo asse. Pertanto, per un caso di input 2D, non cambia. Per un caso di input 1D, crea un array 2D con tutti gli elementi "spinti" sul primo asse a causa di ar.shape[0], che era il numero totale di elementi.

Esempio corre

caso 1D:

In [87]: ar 
Out[87]: array([ 0.80203158, 0.25762844, 0.67039516, 0.31021513, 0.80701097]) 

In [88]: ar.reshape(ar.shape[0],-1) 
Out[88]: 
array([[ 0.80203158], 
     [ 0.25762844], 
     [ 0.67039516], 
     [ 0.31021513], 
     [ 0.80701097]]) 

Caso 2D:

In [82]: ar 
Out[82]: 
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523], 
     [ 0.39728524, 0.03952238, 0.04153052, 0.82009233], 
     [ 0.38748174, 0.51377738, 0.40365096, 0.74823535]]) 

In [83]: ar.reshape(ar.shape[0],-1) 
Out[83]: 
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523], 
     [ 0.39728524, 0.03952238, 0.04153052, 0.82009233], 
     [ 0.38748174, 0.51377738, 0.40365096, 0.74823535]]) 
+1

Una variante di questa risposta è: 'x = np.reshape (x, (len (x), - 1))', che si occupa anche del caso in cui l'input è una lista 1d o 2d. –

+0

@LucaCiti rendere questa una risposta separata in modo da poter votare. –

+0

Fatto. Grazie per la tua raccomandazione –

0

ho chiesto dtype perché il vostro esempio è sconcertante.

posso fare una serie strutturato con 3 elementi (1d) e 3 campi:

In [1]: A = np.ones((3,), dtype='i,i,i') 
In [2]: A 
Out[2]: 
array([(1, 1, 1), (1, 1, 1), (1, 1, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')]) 

posso accedere un campo per nome (tra parentesi l'aggiunta non cambia le cose)

In [3]: A['f0'].shape 
Out[3]: (3,) 

ma se accedo 2 campi, ho ancora ottenere un allineamento 1d

In [4]: A[['f0','f1']].shape 
Out[4]: (3,) 
In [5]: A[['f0','f1']] 
Out[5]: 
array([(1, 1), (1, 1), (1, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 

In realtà quei parentesi in più sono importanti, se io Loo k a valori

In [22]: A['f0'] 
Out[22]: array([1, 1, 1], dtype=int32) 
In [23]: A[['f0']] 
Out[23]: 
array([(1,), (1,), (1,)], 
     dtype=[('f0', '<i4')]) 

Se la matrice è semplice 2d, io ancora non capisco le forme

In [24]: A=np.ones((3,3),int) 
In [25]: A[0].shape 
Out[25]: (3,) 
In [26]: A[[0]].shape 
Out[26]: (1, 3) 
In [27]: A[[0,1]].shape 
Out[27]: (2, 3) 

Ma alla domanda di assicurarsi un array è 2d, a prescindere dal fatto che il indicizzazione restituisce 1D o 2, la funzione è fondamentalmente ok

def reshape_to_vect(ar): 
    if len(ar.shape) == 1: 
     return ar.reshape(ar.shape[0],1) 
    return ar 

Si potrebbe testare ar.ndim invece di len(ar.shape). Ma in entrambi i casi non è costoso - cioè, il tempo di esecuzione è minimo - nessuna grande operazione di array. reshape non copia i dati (a meno che le tue falcate siano strane), quindi è solo il costo di creare un nuovo oggetto array con un puntatore dati condiviso.

Consultare il codice per np.atleast_2d; prova per 0d e 1d. Nel caso 1d restituisce result = ary[newaxis,:]. Aggiunge prima l'asse extra, più naturale è la posizione numpy per l'aggiunta di un asse. Lo aggiungi alla fine.

ar.reshape(ar.shape[0],-1) è un modo intelligente di ignorare il test if. Nei piccoli test di temporizzazione è più veloce, ma stiamo parlando di microsecondi, l'effetto di un livello di chiamata di funzione.

np.column_stack è un'altra funzione che crea array di colonne, se necessario. Esso utilizza:

if arr.ndim < 2: 
     arr = array(arr, copy=False, subok=True, ndmin=2).T 
+0

Ok, ho rimosso l'esempio. Stavo cercando di dare un esempio concreto, ma se è confuso, è meglio non averlo. – DevShark

0

Per evitare la necessità di rimodellare in primo luogo, se si fetta di una riga/colonna con una lista, o una fetta "esecuzione", si otterrà una matrice 2D con una sola riga/colonna

import numpy as np 
x = np.array(np.random.normal(size=(4,4))) 
print x, '\n' 

Result: 
[[ 0.01360395 1.12130368 0.95429414 0.56827029] 
[-0.66592215 1.04852182 0.20588886 0.37623406] 
[ 0.9440652 0.69157556 0.8252977 -0.53993904] 
[ 0.6437994 0.32704783 0.52523173 0.8320762 ]] 

y = x[:,[0]] 
print y, 'col vector \n' 
Result: 
[[ 0.01360395] 
[-0.66592215] 
[ 0.9440652 ] 
[ 0.6437994 ]] col vector 


y = x[[0],:] 
print y, 'row vector \n' 

Result: 
[[ 0.01360395 1.12130368 0.95429414 0.56827029]] row vector 

# Slice with "running" index on a column 
y = x[:,0:1] 
print y, '\n' 

Result: 
[[ 0.01360395] 
[-0.66592215] 
[ 0.9440652 ] 
[ 0.6437994 ]] 

Invece se si utilizza un unico numero per la scelta del riga/colonna, che si tradurrà in un array 1D, che è la causa principale del problema:

y = x[:,0] 
print y, '\n' 

Result: 
[ 0.01360395 -0.66592215 0.9440652 0.6437994 ] 
4

il modo più semplice:

ar.reshape(-1, 1) 
2

Una variante della risposta di divakar è: x = np.reshape(x, (len(x),-1)), che si occupa anche del caso in cui l'input è una lista 1d o 2d.