Chciałbym pokazać alternatywny sposób robienia tego rodzaju rzeczy, nawet często mam wrażenie, że nie jest to doceniane w ten sposób: używając 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"
)
)
Kod wydaje się skomplikowane, ale nie jest i ma pewną przewagę, jak widać w wynikach:
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
Jedną z zalet jest to, że używasz oryginalnego dataframe (bez konwersji do innego klasy) i otrzymujesz ramkę danych (umieść ją w res < - ....). Kolejną zaletą jest to, że wciąż masz wszystkie wiersze. Trzecią zaletą jest to, że można łatwo rozważyć czynniki grupujące.Na przykład:
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 Dobra sztuczka z główkami i ogonami. –
+1 pomysłowy. Nigdy bym nie pomyślał, że 'head' z -1 zwróci wszystko oprócz pierwszego rzędu. Clever –