2014-12-22 10 views
6

Mi aspettavo np.fromfunction(lambda i: 1, (4,), dtype=int) per restituire array([1, 1, 1, 1]), ma restituisce invece il numero intero 1. Qualcuno può spiegarmi perché numpy.fromfunction si comporta in questo modo? Sembra avere qualcosa a che fare con la definizione della funzione anonima (cioè, se un parametro della funzione è effettivamente usato).Risultato imprevisto - numpy dalla funzione con funzioni costanti

>>> import numpy as np 

>>> np.fromfunction(lambda i: i, (4,), dtype=int) 
array([0, 1, 2, 3]) 

>>> np.fromfunction(lambda i: 1, (4,), dtype=int) 
1 

>>> np.fromfunction(lambda i: 1 + i*0, (4,), dtype=int) 
array([1, 1, 1, 1]) 

EDIT: Per chiarire, il mio obiettivo finale non è quello di creare array([1, 1, 1, 1]) utilizzando questo metodo. Piuttosto, sto facendo una chiamata di modulo

np.fromfunction(lambda i: **an expression that doesn't depend on i**, (n,)) 

In altre parole, sto cercando di inizializzare una matrice NumPy ripetutamente effettuando una chiamata ad una funzione. (C'è una chiamata a np.random.random() in quella funzione, quindi non sto facendo le chiamate ridondanti.)

+0

Se l'espressione non dipende da 'i', sospetto che si possa sostituire l'uso di' a = np.fromfunction (lambda i: ** un'espressione che non dipende da i **, (n,)) 'con qualcosa come' a = ** un'espressione che non dipende da i ** ', e nell'espressione usa qualcosa come' np.ones (n) ',' np.arange (n) ', ecc., per fare in modo che l'espressione crei una matrice della dimensione appropriata. –

+0

@WarrenWeckesser Non sono sicuro di aver capito. Il tuo metodo funzionerà anche se c'è una chiamata a 'np.random.random()' dentro '** un'espressione che non dipende da i ** '? –

+0

Puoi usare l'argomento 'size' di' np.random.random'. Se la tua espressione è, per esempio, '4 * u ** 2 + 1' dove' u' è casuale, puoi scrivere 'a = 4 * np.random.casuale (dimensione = n) ** 2 + 1'. –

risposta

6

Non è spiegato bene nella documentazione dell'argomento func nel fromfunction docstring che func si chiama solo una volta, con argomenti di matrice.

In questo esempio

np.fromfunction(lambda i: i, (4,), dtype=int) 

la funzione anonima viene chiamato una volta, con l'argomento i essendo l'array [0, 1, 2, 3]. Per verificare questo, si può fare:

In [10] from __future__ import print_function 

In [11]: np.fromfunction(lambda i: print("i = %r" % (i,)), (4,), dtype=int) 
i = array([0, 1, 2, 3]) 

In questo caso, in cui func restituisce 1,

np.fromfunction(lambda i: 1, (4,), dtype=int) 

perché il valore restituito dalla singola chiamata è 1, la matrice che viene creato contiene solo 1 .

non è chiaro il motivo per cui si desidera utilizzare fromfunction per creare una serie di 1s, invece di, diciamo, np.ones, ma nel caso in cui si ha qualcosa di più complicato in mente, ecco un modo si potrebbe farlo, utilizzando np.ones_like:

In [14]: np.fromfunction(lambda i: np.ones_like(i), (4,), dtype=int) 
Out[14]: array([1, 1, 1, 1]) 
+2

Questo sembra abbastanza poco intuitivo. Esiste una funzione che fa ciò che l'OP intende fare? – Rufflewind

+0

Grazie - questo chiarisce il comportamento di fromfunction. –

6

@Warren Weckesser ha spiegato perché questo sta accadendo (i documenti NumPy sono un po 'fuorviante qui e non mettere in chiaro che fromfunction si aspetta un vettore). Se si vuole rendere il vostro lavoro lambda funzione con fromfunction si può vettorizzare esplicitamente:

In [1]: func = lambda i: 1 
In [1]: vfunc = np.vectorize(func) 
In [2]: np.fromfunction(vfunc, (4,), dtype=int) 
Out[2]: array([1, 1, 1, 1]) 

Ma per questo caso d'uso, avrei pensato

np.ones(4, dtype=int) 

(forse volte una costante) sarebbero meglio.

+0

Ah, è utile saperlo. Grazie! –

Problemi correlati