Dear R Users, I request your help to optimize a loop. Given a series of observations, I want to know how many consecutive past observations are below the last one. e.g : my_series <- c(3, 4, 10,14,8,3,4,6,9) As the last number (9) is higher than the four preceding numbers (6, 4, 3, 8), this function should return 4. my_series <- c(3, 4, 10,14,8,3,4,11,9) Here, it should return 0, as 9 is immediately preceeded by a higher number. So far, I do this awful loop : result <- 0 for (i in 1:length(my_series-1)) { if (my_series[length(my_series)-i]>end(my_series)[1]) { result <- i-1 ; break } } I thing there's a better way... my_series > my_series[end][1] returns : TRUE TRUE FALSE FALSE TRUE TRUE TRUE TRUE FALSE , which seems more appealing (once the last "FALSE" is removed), but now, how to know the size of the last consecutive series of "TRUE" ? Can you see a better way ? Thanks.
Hi discard your loop do not optimise it. rle is your friend> my_fun<-function(x) {+ + len<-length(x) + x1<-rle(x[len]>x[1:len-1]) + last<-length(x1$values) + ifelse(x1$values[last],x1$lengths[last],0) + }> my_fun(my_series)[1] 0> my_series <- c(3, 4, 10,14,8,3,4,6,9) > my_fun(my_series)[1] 4>and vectorise, vectorise, vectorise. HTH Petr On 18 Jan 2007 at 14:11, Nicolas Prune wrote: Date sent: Thu, 18 Jan 2007 14:11:11 +0100 From: Nicolas Prune <np at alambic.org> To: r-help at stat.math.ethz.ch Subject: [R] How to optimize this loop ?> Dear R Users, > > I request your help to optimize a loop. > > Given a series of observations, I want to know how many consecutive > past observations are below the last one. > > e.g : > my_series <- c(3, 4, 10,14,8,3,4,6,9) > > As the last number (9) is higher than the four preceding numbers (6, > 4, 3, 8), this function should return 4. > > my_series <- c(3, 4, 10,14,8,3,4,11,9) > Here, it should return 0, as 9 is immediately preceeded by a higher > number. > > So far, I do this awful loop : > > result <- 0 > for (i in 1:length(my_series-1)) > { > if (my_series[length(my_series)-i]>end(my_series)[1]) > { result <- i-1 ; break } > } > > I thing there's a better way... > > my_series > my_series[end][1] returns : > TRUE TRUE FALSE FALSE TRUE TRUE TRUE TRUE FALSE > , which seems more appealing (once the last "FALSE" is removed), but > now, how to know the size of the last consecutive series of "TRUE" ? > > Can you see a better way ? > > Thanks. > > ______________________________________________ > R-help at stat.math.ethz.ch 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.Petr Pikal petr.pikal at precheza.cz
Nicolas Prune wrote:> Dear R Users, > > I request your help to optimize a loop. > > Given a series of observations, I want to know how many consecutive past > observations are below the last one. > > e.g : > my_series <- c(3, 4, 10,14,8,3,4,6,9) > > As the last number (9) is higher than the four preceding numbers (6, 4, 3, 8), > this function should return 4. > > my_series <- c(3, 4, 10,14,8,3,4,11,9) > Here, it should return 0, as 9 is immediately preceeded by a higher number. > > So far, I do this awful loop : > > result <- 0 > for (i in 1:length(my_series-1)) > { > if (my_series[length(my_series)-i]>end(my_series)[1]) > { result <- i-1 ; break } > } > > I thing there's a better way...Just in terms of finding out which values are bigger than the preceding value and avoiding the explicit loop, you could do something like this: seriesA <- c(3,4,10,14,8,3,4,6,9) seriesB <- c(3,4,10,14,8,3,4,11,9) sign(diff(seriesA)) == 1 [1] TRUE TRUE TRUE FALSE FALSE TRUE TRUE TRUE sign(diff(seriesB)) == 1 [1] TRUE TRUE TRUE FALSE FALSE TRUE TRUE FALSE> my_series > my_series[end][1] returns : > TRUE TRUE FALSE FALSE TRUE TRUE TRUE TRUE FALSE > , which seems more appealing (once the last "FALSE" is removed), but now, how to > know the size of the last consecutive series of "TRUE" ? > > Can you see a better way ? > > Thanks. > > ______________________________________________ > R-help at stat.math.ethz.ch 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.-- Chuck Cleland, Ph.D. NDRI, Inc. 71 West 23rd Street, 8th floor New York, NY 10010 tel: (212) 845-4495 (Tu, Th) tel: (732) 512-0171 (M, W, F) fax: (917) 438-0894
Thanks to everyone who answered, in public or in private. I successfully rewrote my function with rle. For my sample, the total computation times (I call this function around 1000 times) are roughly the same. However, I thank you for letting me know rle, and S Poetry. Regards, Nicolas
>Given a series of observations, I want to know how many consecutivepast>observations are below the last one.prune=function(m) { mr=rev(m) ms=cumsum(mr < mr[1]) sum(seq_along(ms) - ms == 1) - 1 } prune(c(3, 4, 10, 14, 8, 3, 4, 8, 9)) # 4 prune(c(3, 4, 10, 14, 8, 3, 4, 11, 9)) # 0 Heikki Kaskelma