Lucas Fortini
Lucas Fortini

Reputation: 2480

How to vectorize complex iterative loop in r

I usually have no problem with vectorization in r, but I am having a tough time in the example below where there are both iterative and non-iterative components in the for loop.

In the code below, I have a calculation that I have to perform based on a set of constants (Dini), a vector of values (Xs), where the ith value of the output vector (Ys) is also dependent on i-1 value:

Dini=128 #constant
Xs=c(6.015, 5.996, 5.989, 5.911, 5.851, 5.851, 5.858, 5.851)
Y0=125.73251 #starting Y value

Ys=c(Y0) #starting of output vector, first value is known
for (Vi in Xs[2:length(Xs)]){
  ytm1=Ys[length(Ys)]
  y=(955.74301-2*((Dini+ytm1-Vi)^2-ytm1^2)^0.5+2*ytm1*acos(ytm1/(Dini+ytm1-Vi)))/pi/2
  Ys=c(Ys, y)
} 
df=data.frame(Xs, Ys)
df

    Xs       Ys
1 6.015 125.7325
2 5.996 125.7273
3 5.989 125.7251
4 5.911 125.7036
5 5.851 125.6859
6 5.851 125.6849
7 5.858 125.6868
8 5.851 125.6850

For this case, where there is a mix of both iterative and non iterative components in the for loop, my mind has got twisted in a non-vectorized knot.

Any suggestions?

Upvotes: 2

Views: 288

Answers (1)

MrFlick
MrFlick

Reputation: 206616

You might want to look into use Reduce in this case. For example

Ys<-Reduce(function(prev, cur) { 
  (955.74301-2*((Dini+prev-cur)^2-prev^2)^0.5 + 2*prev*acos(prev/(Dini+prev-cur)))/pi/2
}, Xs, init=Y0, accumulate=T)[-1]

From the ?Reduce help page: "Reduce uses a binary function to successively combine the elements of a given vector and a possibly given initial value." This makes it easier to create vectors where a given value depends on a previous value.

Upvotes: 4

Related Questions