2015-09-22 16 views
8

Vorrei sapere se è possibile applicare una funzione (o giustificare un'operazione, ad esempio la sostituzione di valori) a una colonna in un array Python 2d, senza utilizzare loop.Operazione su colonne di array 2d

Mi dispiace se la domanda è già stata fatta, ma non ho trovato nulla di specifico sul mio problema.

mi piacerebbe fare qualcosa di simile:

array[:][2] = 1 

che significherebbe messo 1 per ogni valore alla terza colonna, o

func(array[:][2]) 

che significherebbe applicano func() a la terza riga dell'array.

C'è qualche modo magico in pitone per farlo?

EDIT: La verità è stata detta. Ho dimenticato di dire che non volevo evitare la dichiarazione for() per migliorare le prestazioni, ma solo perché non voglio aggiungere linee multiple per questa istanza precisa. Abbiamo ottenuto 2 risposte qui, una in modo nativo e altre due con l'aiuto di Numpy. Grazie mille per le tue risposte!

risposta

7

Senza NumPy si può fare in questo modo:

map(lambda x: x[:2] + [1] + x[3:], array) 

map(lambda x: x[:2] + my_func(x[2]) + x[3:], array) 
+0

Non utilizza, ma itera attraverso l'elenco, che richiede più tempo della soluzione numpy. Ad ogni modo, buona risposta. –

+0

Dato che mi piacerebbe usare Python nativo, questa è la soluzione migliore per me. Molte grazie ! – Coulis

7

È possibile farlo facilmente con gli array numpy. Esempio -

In [2]: import numpy as np 

In [3]: na = np.array([[1,2,3],[3,4,5]]) 

In [4]: na 
Out[4]: 
array([[1, 2, 3], 
     [3, 4, 5]]) 

In [5]: na[:,2] = 10 

In [6]: na 
Out[6]: 
array([[ 1, 2, 10], 
     [ 3, 4, 10]]) 

In [7]: na[:,2] 
Out[7]: array([10, 10]) 

In [8]: def func(a): 
    ...:  for i,x in enumerate(a): 
    ...:   a[i] = x + 1 
    ...: 

In [9]: na 
Out[9]: 
array([[ 1, 2, 10], 
     [ 3, 4, 10]]) 

In [10]: func(na[:,1]) 

In [11]: na 
Out[11]: 
array([[ 1, 3, 10], 
     [ 3, 5, 10]]) 

È possibile trovare maggiori dettagli su questo here. Si prega di fare attenzione, per gli array NumPy, come affermato in documentation -

Tutti gli array generati da affettare di base sono sempre views della matrice originale.

Ecco perché quando si modifica la matrice a fette all'interno della funzione, la matrice effettiva è stata modificata.

2

Sarebbe molto semplice nel NumPy e si può fare con un semplice assegnazione:

>>> numpy.array[:,column_number]=value 

Ma se siete alla ricerca di un approccio pitone è possibile utilizzare la funzione zip e itertools.repeat():

>>> from itertools import repeat 
>>> def replacer(l,index,value): 
...  z=zip(*l) 
...  z[index]=list(repeat(value,len(l))) 
...  return zip(*z) 

Demo:

>>> l=[range(4) for _ in range(3)] 
>>> replacer(l,2,'*') 
[(0, 1, '*', 3), (0, 1, '*', 3), (0, 1, '*', 3)] 

Nota che, dal momento in 3.X pitone zip restituisce un iteratore è possibile utilizzare la funzione list per restituire un elenco anche perché iteratori non supporta l'indicizzazione all'interno della funzione è necessario chiamare la lista troppo.

>>> def replacer(l,index,value): 
...  z=list(zip(*l)) 
...  z[index]=list(repeat(value,len(l))) 
...  return zip(*z) 

>>> list(replacer(l,2,'*')) 
[(0, 1, '*', 3), (0, 1, '*', 3), (0, 1, '*', 3)] 
+0

Ci scusiamo per il ritardo LUNGO, ma mi piacerebbe sapere qualcosa. È una buona pratica usare librerie come numpy, scipy, ecc. Per un gioco? Questo problema di array riguardava l'inizializzazione della mappa per un gioco 2D, ma mi chiedevo se fosse "buono" utilizzare le librerie scientifiche per alleggerire il mio codice. – Coulis

2

è possibile associare una funzione a ciascuna colonna ....

ar = [[1,2,3], 
     [3,4,5], 
     [3,4,5], 
     [3,4,5], 
     [3,4,5]] 

if you want change second column to 100: 

    def column_change(l,n =1 , m =100): 
     l[n] = m 
     return l 

    print(list(map(colum_change,ar))) 

    [[1, 100, 3], [3, 100, 5], [3, 100, 5], [3, 100, 5], [3, 100, 5]]