1

I am calculating angles for each point with 'for' loop. But somehow the matrix is not populated as desirable. Only the first element in matrix is populated with calculated value.

w1 = c(-2.40154, -1.82937)
w2 = c(-2.079041, 101,0663)
xy = as.data.frame(coordinates(p))
angle  = function (w1, w2 , p, ...) {
   iterations = 2500
   a = sqrt ((w1[1]-w2[1])^2 + (w1[2]-w2[2])^2)
   tr <- matrix(ncol=1, nrow=iterations)
  for (i in 1:iterations) { 
    b[i] = sqrt ((p$coords.x1[i]-w1[1])^2 + (p$coords.x2[i]-w1[2])^2)
    c[i] = sqrt ((p$coords.x1[i]-w2[1])^2 + (p$coords.x2[i]-w2[2])^2)
    tr[i,] = (acos ((b[i]^2 + c[i]^2 - a^2)/ (2*b[i]*c[i]))*180)/pi
    print(tr)   
  }
  return(tr)
}
t = angle(w1,w2,xy)

tr is getting only the first value. Please correct the code.

Jio
  • 578
  • 3
  • 8
  • 27
  • 2
    Shouldn't your `return(tr)` be outside the `for` loop? Otherwise only one iteration will happen. Also, you appear to be overwriting `tr` for each iteration. Is that your intention? – MrFlick Jun 04 '15 at 18:34
  • It looks like your brackets are mismatched. Also you should probably put `tr` outside of the loop. – pbible Jun 04 '15 at 18:35
  • 2
    You want to put `tr <- matrix(ncol=1, nrow=iterations)` right after `iterations = 2500` – Vlo Jun 04 '15 at 18:37

3 Answers3

3

Usually you don't want to loop through vectors performing one index at a time. You instead want to operate on the vectors as a whole. This will make your code both shorter and more efficient:

w1 = c(-2.40154, -1.82937)
w2 = c(-2.079041, 101,0663)
p <- data.frame(coords.x1=c(4, 5), coords.x2=c(6, 7))
angle <- function(w1, w2, p) {
  a <- sqrt ((w1[1]-w2[1])^2 + (w1[2]-w2[2])^2)
  b <- sqrt ((p$coords.x1-w1[1])^2 + (p$coords.x2-w1[2])^2)
  c <- sqrt ((p$coords.x1-w2[1])^2 + (p$coords.x2-w2[2])^2)
  return(matrix((acos ((b^2 + c^2 - a^2)/ (2*b*c))*180)/pi, ncol=1))
}
angle(w1, w2, p)
#          [,1]
# [1,] 137.0681
# [2,] 135.7206

Basically all I did was remove the for loop and the indexing by i and your code works as expected.

josliber
  • 43,891
  • 12
  • 98
  • 133
0

You probably want to

return(tr)

after all passes through the for loop are done, not during the first pass through it.

EDIT: @josilber's answer is much better. This function is easily vectorizable as he shows.

rcorty
  • 1,140
  • 1
  • 10
  • 28
0

You did not tell us how is p defined. If you insist in using your code, iterations need to depend on rows of p.

w1 = c(-2.40154, -1.82937)
w2 = c(-2.079041, 101.0663)
p <- data.frame(coords.x1=c(4, 5,3), coords.x2=c(6, 7,5))
xy = as.data.frame(p)
angle1  = function (w1, w2 , p, ...) {
  iterations = nrow(p)
  b<-c<-vector()
  tr <- matrix(ncol=1, nrow=iterations)
  a = sqrt ((w1[1]-w2[1])^2 + (w1[2]-w2[2])^2)

  for (i in 1:iterations) { 
    b[i] = sqrt ((p$coords.x1[i]-w1[1])^2 + (p$coords.x2[i]-w1[2])^2)
    c[i] = sqrt ((p$coords.x1[i]-w2[1])^2 + (p$coords.x2[i]-w2[2])^2)    
    tr[i,] = (acos ((b[i]^2 + c[i]^2 - a^2)/ (2*b[i]*c[i]))*180)/pi
    #print(tr)
    }
  return(tr)
}
t = angle1(w1,w2,xy)
head(t)
         [,1]
[1,] 137.0707
[2,] 135.7236
[3,] 138.6321
Robert
  • 5,038
  • 1
  • 25
  • 43
  • Thanks Robert. Point noted. However, 'p' has innumerous records, for testing purpose i only wanted to iterate a reasonable number of times. So i defined iteration = 2500.Importantly, what i learned here is that vectors in R do not have to be iterated unlike arrays in conventional programming language. And i dont insist on using my code. – Jio Jun 06 '15 at 22:02