2014-04-28 16 views
6

Nel mio programma di R Ho un ciclo "for" della forma seguente:Come evitare un loop qui in R?

for(i in 1:I) 
{ 
res[i] <- a[i:I] %*% b[i:I] 
} 

dove res, a e b sono vettori di lunghezza I.

Esiste un modo semplice per evitare questo ciclo e calcolare direttamente la ris.? Se così fosse, sarebbe più efficiente?

Grazie in anticipo!

+1

Perché stai usando una moltiplicazione di matrici per i vettori 1d? –

+3

Probabilmente perché sono autodidatta e clueless ... – Martin

risposta

9

Questo è il "cumSum inversa" di a*b

rev(cumsum(rev(a) * rev(b))) 
+0

cronometro in corso ... :-) –

+0

@CarlWitthoft vai avanti, ma con 'cumsum()' la moltiplicazione avviene solo una volta, quindi viene eseguita in _O (n) _. Il ciclo dovrebbe essere eseguito in _O (n^2) _. – ilir

+2

Anche sostituendo '% *%' con '*' in Justin, i tempi medi sono 360 e 87700 microsecondi, quindi nessuna sorpresa 'cumsum' è più veloce di molto. –

2

Fintanto che res è già di lunghezza I, il ciclo for non è "errato" e le soluzioni di applicazione non saranno più veloci. Tuttavia, utilizzando applicare può essere più succinta ... (se potenzialmente meno leggibile)

Qualcosa di simile a questo:

res <- sapply(seq_along(a), function(i) a[i:I] %*% b[i:I]) 

dovrebbe funzionare come un one-liner.


Espansione sulla prima frase. Mentre utilizzare la vettorizzazione intrinseca disponibile in R è molto utile e spesso la via più veloce da percorrere, non sempre è fondamentale evitare cicli di loop. Sotto, la famiglia apply determina la dimensione dell'output e la pre-alloca prima del "looping".

+0

Giusto per essere chiari - questo non accelera il calcolo rispetto a quello di un ciclo, vero? –

+0

corretto. Se il codice nel ciclo for era 'res <- rbind (res, ...)' allora la versione apply sarebbe molto più veloce. – Justin

+1

Inoltre, usare 'sum (a [i: 1] * b [i: 1])' dovrebbe essere leggermente più veloce della moltiplicazione della matrice. – ilir