2012-03-01 7 views
19

In NumPy, come si può rendere efficiente un oggetto 1-D in un oggetto 2D in cui la dimensione singleton viene dedotta dall'oggetto corrente (ad esempio una lista dovrebbe andare a un vettore 1xlength o lengthx1)?Modo efficiente per aggiungere una dimensione singleton a un vettore NumPy in modo che le assegnazioni slice funzionino

# This comes from some other, unchangeable code that reads data files. 
my_list = [1,2,3,4] 

# What I want to do: 
my_numpy_array[some_index,:] = numpy.asarray(my_list) 

# The above doesn't work because of a broadcast error, so: 
my_numpy_array[some_index,:] = numpy.reshape(numpy.asarray(my_list),(1,len(my_list))) 

# How to do the above without the call to reshape? 
# Is there a way to directly convert a list, or vector, that doesn't have a 
# second dimension, into a 1 by length "array" (but really it's still a vector)? 

risposta

38

Nel caso più generale, il modo più semplice per aggiungere dimensioni extra ad una matrice viene utilizzando la parola chiave None quando indicizza nella posizione per aggiungere la dimensione extra. Per esempio

my_array = numpy.array([1,2,3,4]) 

my_array[None, :] # shape 1x4 

my_array[:, None] # shape 4x1 
+3

Questo è ciò che fa 'np.atleast_2d ([1,2,3,4])'. – hpaulj

+0

@hpaulj sì, ma l'approccio di @DaveP è pulito, salva la seccatura di cercare 'np.atleast_2d' nei documenti e generalizza agli array n-dim (dove n> 3 b/c so che c'è un' np .atleast_3d'). – BoltzmannBrain

+0

Ora c'è un 'np.expand_dims' per gestire tutte le dimensioni. – hpaulj

4

Perché non aggiungere semplicemente parentesi quadre?

>> my_list 
[1, 2, 3, 4] 
>>> numpy.asarray([my_list]) 
array([[1, 2, 3, 4]]) 
>>> numpy.asarray([my_list]).shape 
(1, 4) 

.. aspetta, a pensarci bene, perché il tuo servizio di slice non funziona? Non dovrebbe:

>>> my_list = [1,2,3,4] 
>>> d = numpy.ones((3,4)) 
>>> d 
array([[ 1., 1., 1., 1.], 
     [ 1., 1., 1., 1.], 
     [ 1., 1., 1., 1.]]) 
>>> d[0,:] = my_list 
>>> d[1,:] = numpy.asarray(my_list) 
>>> d[2,:] = numpy.asarray([my_list]) 
>>> d 
array([[ 1., 2., 3., 4.], 
     [ 1., 2., 3., 4.], 
     [ 1., 2., 3., 4.]]) 

anche:

>>> d[1,:] = (3*numpy.asarray(my_list)).T 
>>> d 
array([[ 1., 2., 3., 4.], 
     [ 3., 6., 9., 12.], 
     [ 1., 2., 3., 4.]]) 
+0

Non sicuro. Sto esaminando l'errore di trasmissione in questo momento, ma sembra essere dovuto alla mia versione di NumPy (1.5.1). L'idea di parentesi quadrata che hai menzionato funziona per il mio problema attuale. Non sono sicuro di quanto sia fattibile per elenchi di grandi dimensioni ... Python è astuto dal non aggiungere un sacco di spese generali per passare da un elenco di, ad esempio, a 100.000 articoli a un elenco contenente un elenco di 100.000 elementi? – ely

+1

Probabilmente non è così intelligente come vorresti che fosse - gli elenchi Python e gli array numpy non condividono i dati. Ma se hai già la lista da altrove, non ci sono spese generali per aggiungere le parentesi quadre se per qualche ragione ne hai bisogno: prova 'a = [1,2]; b = [a]; print b [0] è a', e vedi che Python non sta facendo una nuova copia di a, sta riutilizzando l'originale. – DSM

1

È sempre possibile utilizzare dstack() per replicare l'array:

import numpy 

my_list = array([1,2,3,4]) 
my_list_2D = numpy.dstack((my_list,my_list)); 
2
import numpy as np 
a = np.random.random(10) 
sel = np.at_least2d(a)[idx] 
3

Che dire expand_dims?

np.expand_dims(np.array([1,2,3,4]), 0) 

ha forma (1,4) mentre

np.expand_dims(np.array([1,2,3,4]), 1) 

ha forma (4,1).

0

Da python3.5, è possibile utilizzare anche l'estrazione con np.ndarray.shape all'interno np.reshape:

>>> my_array = np.array([1,2,3,4]) 
>>> my_array.reshape(1, *my_array.shape) 
array([[1, 2, 3, 4]]) 
>>> my_array.reshape(*my_array.shape, 1) 
array([[1], 
     [2], 
     [3], 
     [4]]) 

my_array.reshape(1, *my_array.shape) opere nelle vecchie versioni pure, ma non il secondo.

Problemi correlati