[R] avoiding a loop

Duncan Murdoch murdoch at stats.uwo.ca
Tue Oct 24 21:04:33 CEST 2006


On 10/24/2006 2:53 PM, Jerome Asselin wrote:
> On Tue, 2006-10-24 at 14:36 -0400, Leeds, Mark (IED) wrote:
>> I think I asked a similar question 3 years ago to the  Splus list and I
>> think the answer was no or noone answered so noone should spend more
>> than 5 minutes on this 
>> because it could definitely be a waste of time.
>>  
>> My question is whether the function below can be rewritten without a for
>> loop. apply is fine if it can be done that way but i doubt it. I call it
>> a lot and would
>> prefer to not loop.
>>  
>> #-----------------------------------------------------------------------
>> --------------------------
>>  
>> constructLt<-function(invector) {
>>  
>> outvector<-invector
>>  
>>  for ( i in 2:length(invector) ) {
>>  if ( invector[i] < 1 ) {
>>   outvector[i]<-invector[i]*outvector[i-1]
>>  }
>> }
>>  
>> return(outvector)
>>  
>> }
> 
> You sure can vectorize this. Try this below... I haven't tested, but it
> should be close to your solution. There's also 
> 
> a <- invector[-1]
> outvector <- invector
> wh <- which(a<1)+1
> outvector[wh] <- a[wh] * invector[-length(invector)][wh-1]
> outvector

I think this misses the fact that if a sequence of invector values are 
less than 1, then the multiplication accumulates:  e.g. with invector 
equal to rep(0.5, 5) the output should be

 > constructLt(rep(0.5,5))
[1] 0.50000 0.25000 0.12500 0.06250 0.03125

whereas your function gives

 > asselin(rep(0.5,5))
[1] 0.50 0.25 0.25 0.25   NA

A function like filter() might be able to do this, but in general R 
doesn't give a way to write recursive formulae in a simple vector form.

In this particular case, I'd just use the for loop; if it turned out to 
be too slow, I'd rewrite it in C, in a nearly literal translation.

Duncan Murdoch



More information about the R-help mailing list