Reputation: 445
I am trying to create a function in r for exponential smoothing.
I have been able to create what I need in excel using a formula:
=(alpha*observed+(alpha - 1)*previous)
This can easily be dragged down and achieves the desired result. Here is an example of this with alpha = 0.1.
Score <- c(4,7,3,5,7,2,3)
Score Exp Smooth Calculation
4 #N/A #N/A
7 4 4
3 4.3 0.1*7+0.9*4
5 4.17 0.1*3+0.9*4.3
7 4.253 0.1*5+0.9*4.17
2 4.5277 0.1*7+0.9*4.253
3 4.27493 0.1*2+0.9*4.5277
I'm sure there must be a way to recreate this as a function in r. Furthermore, I need this function to be able to be grouped over multiple fields. Here is another example with more fields and the desired exponential smoothing figures.
Player <- c('Y','Z','Z','Z','Z','Y','Y','Y','Y','Z','Y','Y','Z','Y','Z','Y','Z','Z','Y','Y','Z','Y','Z','Y','Z','Z','Y')
Team <- c('A','B','A','A','B','A','B','B','A','A','B','B','A','A','A','A','A','A','A','B','B','B','B','A','A','A','A')
Score <- c(5,2,7,3,9,6,3,7,1,7,3,8,3,4,1,9,4,6,3,8,3,4,1,9,4,6,6)
data.frame(Player, Team, Score)
Desired result:
Player Team Score Exp Smooth
Y A 5 #N/A
Z B 2 #N/A
Z A 7 #N/A
Z A 3 7
Z B 9 2
Y A 6 5
Y B 3 #N/A
Y B 7 3
Y A 1 5.1
Z A 7 6.6
Y B 3 3.4
Y B 8 3.36
Z A 3 6.64
Y A 4 4.69
Z A 1 6.276
Y A 9 4.621
Z A 4 5.7484
Z A 6 5.57356
Y A 3 5.05890
Y B 8 3.82400
Z B 3 2.70000
Y B 4 4.24160
Z B 1 2.73000
Y A 9 4.85301
Z A 4 5.616204
Z A 6 5.454584
Y A 6 5.267709
I'm sure there must be a way to achieve this in r. Any help would be much appreciated!
Upvotes: 3
Views: 1921
Reputation: 132706
You can use the filter
function. However, we have to be a bit creative since its recursive filter implies a coefficient of 1 for lag 0.
fun <- function(x) {
res <- stats::filter(x * c(1, rep(0.1, length(x) - 1)), 0.9, method = "recursive")
c(NA, res[-length(res)])
}
Score <- c(4,7,3,5,7,2,3)
fun(Score)
#[1] NA 4.00000 4.30000 4.17000 4.25300 4.52770 4.27493
There is an enormous number of answers on Stack Overflow showing how to apply a function by groups ("split-apply-combine").
Upvotes: 3