2016-01-06 14 views
8

Sono nuovo a R e non riesco a capire come chiamare un valore precedente di "self", in questo caso precedente "b" b[-1].Riferendosi alla riga precedente nel calcolo

b <- ((1/14) * MyData$High + ((13/14)*b[-1])) 

Ovviamente ho bisogno di un NA da qualche parte in là per il primo calcolo, ma io proprio non poteva capirlo da solo.

Aggiunta esempio di ciò che il ricercato risultato dovrebbe essere (A = MyData $ Alta):

A b 
1 5 NA 
2 10 0.7142... 
3 15 3.0393... 
4 20 4.6079... 
+0

Benvenuti in SO, questa è una buona prima domanda +1, tuttavia non è necessario dare un ringraziamento gentile nella domanda qui, anche se sembra carino tende a distrarre dalla domanda ed è meglio mostrare apprezzamento upvoting o accettare risposte. – Vality

+0

Si potrebbe voler cercare e provare lag() da dplyr. Senza conoscere i dati e l'output desiderato, è molto difficile aiutare con una risposta. – Gopala

+1

Si prega di fornire un esempio riproducibile minimo. Questo renderà la tua domanda una "prima buona" prima domanda. –

risposta

5

1) per il ciclo Normalmente si basta usare un semplice ciclo per questo:

MyData <- data.frame(A = c(5, 10, 15, 20)) 


MyData$b <- 0 
n <- nrow(MyData) 
if (n > 1) for(i in 2:n) MyData$b[i] <- (MyData$A[i] + 13 * MyData$b[i-1])/ 14 
MyData$b[1] <- NA 

dono:

> MyData 
    A   b 
1 5  NA 
2 10 0.7142857 
3 15 1.7346939 
4 20 3.0393586 

2) Riduci Sarebbe anche possibile utilizzare Reduce. Un primo definisce una funzione f che effettua il corpo del ciclo e quindi abbiamo Reduce invocare ripetutamente simili:

f <- function(b, A) (A + 13 * b)/14 
MyData$b <- Reduce(f, MyData$A[-1], 0, acc = TRUE) 
MyData$b[1] <- NA 

dare lo stesso risultato.

Questo dà l'impressione di essere vettorializzato, ma in effetti se si guarda la fonte di Reduce fa un ciclo for stesso.

3) filtro Notando che la forma del problema è un filtro ricorsivo con coefficiente 13/14 operante su A/14 (ma con A [1] sostituito da 0) possiamo scrivere quanto segue. Poiché filter restituisce una serie storica, viene utilizzato c(...) per convertirlo in un vettore ordinario. Questo approccio in realtà è vettorizzato come l'operazione di filtro viene eseguita in C.

MyData$b <- c(filter(replace(MyData$A, 1, 0)/14, 13/14, method = "recursive")) 
MyData$b[1] <- NA 

di nuovo dando lo stesso risultato.

Nota: Tutte le soluzioni presuppongono che MyData disponga di almeno una riga.

+0

aggiunto 2 ° e 3 ° approccio –

3

Ci sono un paio di modi per farlo.

Il primo metodo è un semplice ciclo

df <- data.frame(A = seq(5, 25, 5)) 
df$b <- 0 

for(i in 2:nrow(df)){ 
    df$b[i] <- (1/14)*df$A[i]+(13/14)*df$b[i-1] 
} 

df 
A   b 
1 5 0.0000000 
2 10 0.7142857 
3 15 1.7346939 
4 20 3.0393586 
5 25 4.6079758 

Questo non dà i valori esatti riportati nella risposta attesa, ma è abbastanza vicino che ho assunto hai fatto un errore di trascrizione. Nota che dobbiamo supporre che possiamo prendere lo NA in df$b[1] come zero o otteniamo NA fino in fondo.

Se si dispone di un mucchio di dati o è necessario eseguire questa operazione un po 'di tempo, è possibile migliorare la velocità implementando il codice in C++ e richiamandolo da R.

Il secondo metodo utilizza la funzione R sapply

La forma si presenti il ​​problema in

b_i = (1/14)A_i + b_{i-1}

è ricorsiva, che rende impossibile vectorise, tuttavia possiamo fare alcuni calcoli e trova che è equivalente a

b_i=\frac{1}{14}\sum_{j=1}^{j=i}{\left(\frac{13}{14}\right)^{(i-j)}A_j}

Possiamo quindi scrivere una funzione che calcola b_i Utilizzando sapply per calcolare ciascun elemento

calc_b <- function(n,A){ 
    (1/14)*sum((13/14)^(n-1:n)*A[1:n]) 
} 

df2 <- data.frame(A = seq(10,25,5)) 
df2$b <- sapply(seq_along(df2$A), calc_b, df2$A) 
df2 
A   b 
1 10 0.7142857 
2 15 1.7346939 
3 20 3.0393586 
4 25 4.6079758 

Nota: Occorre eliminare la prima riga (dove A = 5) in modo che il calcolo per eseguire correttamente.

Problemi correlati