Mi piacerebbe mostrare un modo alternativo per fare questo genere di cose anche se spesso ho la sensazione che non sia apprezzato farlo in questo modo: usando sql.
sqldf(paste("SELECT a.ID,a.Score"
," , a.Score - (SELECT b.Score"
," FROM df b"
," WHERE b.ID < a.ID"
," ORDER BY b.ID DESC"
," ) diff"
," FROM df a"
)
)
Il codice sembra complicato ma non lo è e ha un certo vantaggio, come si può vedere i risultati:
ID Score diff
1 1 40 <NA>
2 2 36 -4.0
3 3 32 -4.0
4 4 28 -4.0
5 5 24 -4.0
6 6 20 -4.0
7 7 16 -4.0
8 8 12 -4.0
9 9 8 -4.0
10 10 4 -4.0
Un vantaggio è che si utilizza il dataframe originale (senza conversione in altra classi) e ottieni un frame di dati (mettilo in res < - ....). Un altro vantaggio è che hai ancora tutte le righe. E il terzo vantaggio è che puoi facilmente prendere in considerazione i fattori di raggruppamento.Per esempio:
df2 <- data.frame(ID=1:10,grp=rep(c("v","w"), each=5),Score=4*10:1)
sqldf(paste("SELECT a.ID,a.grp,a.Score"
," , a.Score - (SELECT b.Score"
," FROM df2 b"
," WHERE b.ID < a.ID"
," AND a.grp = b.grp"
," ORDER BY b.ID DESC"
," ) diff"
," FROM df2 a"
)
)
ID grp Score diff
1 1 v 40 <NA>
2 2 v 36 -4.0
3 3 v 32 -4.0
4 4 v 28 -4.0
5 5 v 24 -4.0
6 6 w 20 <NA>
7 7 w 16 -4.0
8 8 w 12 -4.0
9 9 w 8 -4.0
10 10 w 4 -4.0
+1 Bel trucco con testa e croce. –
+1 immaginativo. Non penserei mai che 'head' con -1 restituisca tutto tranne la prima riga. Clever –