# [R] sequential for loop

Peter Dalgaard p.dalgaard at biostat.ku.dk
Fri Apr 20 10:01:04 CEST 2007

```Charilaos Skiadas wrote:
> Hi Michael,
> On Apr 20, 2007, at 12:31 AM, Michael Toews wrote:
>
>
>> Hi all,
>>
>> I'm usually comfortable using the *apply functions for vectorizing
>> loops
>> in R. However, my particular problem now is using it in a sequential
>> operation, which uses values evaluated in an offset of the loop
>> vector.
>>
>> Here is my example using a for loop approach:
>>
>> dat <- data.frame(year=rep(1970:1980,each=365),yday=1:365)
>> dat\$value <- sin(dat\$yday*2*pi/365)+rnorm(nrow(dat),sd=0.5)
>> dat\$ca <- dat\$cb <- 0 # consecutive above and below 0
>>
>> for(n in 2:nrow(dat)){
>>   if(dat\$value[n] > 0)
>>     dat\$ca[n] <- dat\$ca[n-1] + 1
>>   else
>>     dat\$cb[n] <- dat\$cb[n-1] + 1
>> }
>>
>> I'm inquiring if there is a straightforward way to vectorize this
>> (or a
>> similar example) in R, since it gets rather slow with larger data
>> frames. If there is no straightforward method, no worries.
>>
>>
> Would this do what you want:
>
> dat <- data.frame(year=rep(1970:1980,each=365),yday=1:365)
> dat\$value <- sin(dat\$yday*2*pi/365)+rnorm(nrow(dat),sd=0.5)
> positives <- dat\$value > 0
> dat\$ca <- cumsum(c(0,positives[-1]))
> dat\$cb <- cumsum(c(0,!positives[-1]))
>
>
I think not (did you run both codes?).  As I read it, Michael wants ca
and cb to count up, then reset to zero on a sign change.

Something like this (only partially tested!)

positives <- dat\$value > 0
chg <- c(0,diff(positives)!= 0)
grp <- cumsum(chg)
ix <- unlist(lapply(table(grp),function(n)1:n))
ca <- ifelse(positives,ix,0)
cb <- ifelse(positives,0,ix)

(or ...as.vector(table(grp))... to avoid useless name calculations)
>> +mt
>>
>
> Department of Mathematics and Computer Science
> Hanover College
>
> ______________________________________________
> R-help at stat.math.ethz.ch mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help