2015-05-06 17 views
6

Supponiamo di avere matrice x e y:Numpy: calcola in base all'elemento precedente?

x = numpy.array([1,2,3,4,5,6,7,8,9,10]) # actual content is the a result of another calculation step 

C'è una formula per y, e ciascun elemento si basa sull'elemento precedente, supponiamo i denota l'indice di y, ogni elemento è:

y[i] = y[i-1] * 2 + x[i] 

Quando si calcola il primo elemento, lasciare y[i-1] = 50. In altre parole, y dovrebbe essere:

[101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236] 

Come faccio a calcolare y con numpy?

+0

Quale sarebbe il valore iniziale di 'y', vale a dire' y [0] '? – Divakar

+0

Bene, c'è un valore di partenza artificiale di 50. –

+0

Cosa c'è di sbagliato nel codice che hai scritto? –

risposta

4

Consente costruire alcuni degli elementi nella sequenza:

y[0] = 2*y[-1] + x[0] 
y[1] = 2*y[0] + x[1] = 4*y[-1] + 2*x[0] + x[1] 
y[2] = 2*y[1] + x[2] = 8*y[-1] + 4*x[0] + 2*x[1] + x[2] 
... 
y[n] = 2**(n+1)*y[-1] + 2**n*x[0] + 2**(n-1)*x[1] + ... + x[n] 

Potrebbe non essere immediatamente evidente, ma si può costruire la sequenza di cui sopra con NumPy fare qualcosa di simile:

n = len(x) 
y_1 = 50 
pot = 2**np.arange(n-1, -1, -1) 
y = np.cumsum(pot * x)/pot + y_1 * 2**np.arange(1, n+1) 
>>> y 
array([ 101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236]) 

Il Il lato negativo di questo tipo di soluzioni è che non sono molto generali: un piccolo cambiamento nel tuo problema può rendere inutile l'intero approccio. Ma ogni volta che puoi risolvere un problema con un po 'di algebra, è quasi certamente andando a battere qualsiasi approccio algoritmico con un margine molto lontano.

+0

Avevo qualcosa di simile pronto per essere pubblicato, bel lavoro! – Divakar

+0

Grazie mille. Questo è esattamente quello che sto cercando. –

-1

Ecco come si fa con Python:

x = [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10] 
y = [50] 
for i in range(len(x)): 
    y.append(y[-1] * 2 + x[i]) 
y = y[1:] 

Si potrebbe desiderare di calcolarlo dall'ultimo elemento per evitare che utilizzando i nuovi valori per il prossimo i.

+1

Suppongo che "come faccio a calcolare * con numpy" implichi una versione vettoriale efficiente. –

+0

@AmiTavory Apparentemente no. Ho chiesto cosa c'è di sbagliato nel suo codice nei commenti e la risposta è stata "è pseudocodice". Ma penso anche che la risposta di Ferdinand Beyers dovrebbe essere quella che viene accettata (e svalutata). –

+0

È ancora più semplice come 'y = [50 * 2 + x [0]]; per v in x [1:]: y.append (y [-1] * 2 + v) 'e la tua soluzione non è ancora corretta. – Zero

4

Se avete bisogno di un calcolo ricorsivo, se il vostro y[i] dovrebbe dipendere dal calcolata y[i-1] dalla stessa corsa, quindi non sembra esserci alcuna soluzione integrata in NumPy, e sarà necessario per calcolare utilizzando una semplice for ciclo :

y = np.empty(x.size) 
last = 50 
for i in range(x.size): 
    y[i] = last = last * 2 + x[i] 

Vai a questa domanda: Is a "for" loop necessary if elements of the a numpy vector are dependant upon the previous element?

in caso contrario, è possibile implementare la formula in una sola riga usando NumPy:

y = np.concatenate(([50], y[:-1])) * 2 + x 

Spiegazione:

y[:-1] 

crea una matrice -sized N-1: y_0, y_1, ... y_N-1.

np.concatenate(([50], y[:-1])) 

crea una matrice -sized N con il primo elemento vostro valore iniziale 50. Quindi questa espressione in fondo è il vostro y[i-1].

Quindi è possibile eseguire l'operazione matematica in base all'aritmetica dell'array numpy.

+0

Bello! E poi cambia il primo elemento di 'y'. – Divakar

+1

L'output non dovrebbe essere '[101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236]'? Mancata corrispondenza con il secondo elemento, immagino? Dovrebbe essere 204 e non 102 – Zero

+2

Questo non sembra gestire la ricorrenza correttamente. Sembra che sia progettato per costruire un intero 'y' array da un vecchio' y' e 'x', mentre il comportamento desiderato sembra essere quello di mantenere la relazione data all'interno di un singolo array' y'; il risultato desiderato sarebbe un punto fisso di questa soluzione. – user2357112

0

Questo è come farlo con NumPy:

import numpy as np 
x = np.array([ 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10 ]) 
y = np.array([ 50 ]) 
for i in np.arange(len(x)): 
    y = np.append(
        y, 
        (y[-1] * 2 + x[i]) 
       ) 
y = y[1:] 

print(y) 
Problemi correlati