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 ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.