Speed up or alternative to 'For' loop
On Jun 10, 2013, at 10:28 AM, Trevor Walker wrote:
I have a For loop that is quite slow and am wondering if there is a faster
option:
df <- data.frame(TreeID=rep(1:500,each=20), Age=rep(seq(1,20,1),500))
df$Height <- exp(-0.1 + 0.2*df$Age)
df$HeightGrowth <- NA #intialize with NA
for (i in 2:nrow(df))
{if(df$TreeID[i]==df$TreeID[i-1])
{df$HeightGrowth[i] <- df$Height[i]-df$Height[i-1]
}
}
Ivoid tests with if(){}e;se(). Use vectorized code, possibly with 'ifelse' but in this case you need a function that does calcualtions within groups.
The ave() function with diff() will do it compactly and efficiently:
df <- data.frame(TreeID=rep(1:5,each=4), Age=rep(seq(1,4,1),5)) df$Height <- exp(-0.1 + 0.2*df$Age) df$HeightGrowth <- NA #intialize with NA
df$HeightGrowth <- ave(df$Height, df$TreeID, FUN= function(vec) c(NA, diff(vec))) df
TreeID Age Height HeightGrowth 1 1 1 1.105171 NA 2 1 2 1.349859 0.2446879 3 1 3 1.648721 0.2988625 4 1 4 2.013753 0.3650314 5 2 1 1.105171 NA 6 2 2 1.349859 0.2446879 7 2 3 1.648721 0.2988625 8 2 4 2.013753 0.3650314 9 3 1 1.105171 NA 10 3 2 1.349859 0.2446879 11 3 3 1.648721 0.2988625 12 3 4 2.013753 0.3650314 13 4 1 1.105171 NA 14 4 2 1.349859 0.2446879 15 4 3 1.648721 0.2988625 16 4 4 2.013753 0.3650314 17 5 1 1.105171 NA 18 5 2 1.349859 0.2446879 19 5 3 1.648721 0.2988625 20 5 4 2.013753 0.3650314 (On my machine it was over six times as fast as the if-based code from Arun. )
David Winsemius Alameda, CA, USA