2

I have a very large table (n=2,723,860) and I want to calculate positive wind direction (0 to 360 degrees) from negative wind direction (-180 to 180 degrees).

One of my loops, a for loop with a nested if and else if statement, takes forever to run (see below).

I am new to R and I am thinking that I just don't have this structured efficiently. Any help on how to better structure this so that it doesn't take so long (currently at 20 minutes and it still isn't done)?

for (j in 1:n){
  if (Jun012015$D[j] < 0){
   Jun012015$D1[j] <- (Jun012015$D[j] * (-1))
  } else if (Jun012015$D[j] > 0){
      Jun012015$D1[j] <- ((Jun012015$D[j] * (-1)) + 360)
  } else {
      Jun012015$D1[j] <- 0
  }
}
timss
  • 9,982
  • 4
  • 34
  • 56
MKWalsh
  • 89
  • 1
  • 1
  • 7
  • 2
    Yourcodewillbemorereadableifyouuseyourspacebar. :) – joran Jan 12 '16 at 18:19
  • I just noticed that sometimes you use Jun012015$D and sometimes Jun012015$D1. Is that a typo or were you trying to store into different variables? – Dason Jan 12 '16 at 18:50

3 Answers3

7

I hope docendo discimus decides to reopen their answer because it was good. Here is the code from their answer (which I will remove if they reopen theirs)

idx1 <- Jun012015$D < 0
idx2 <- Jun012015$D > 0
idx3 <- Jun012015$D == 0

Jun012015$D1[idx1] <- Jun012015$D[idx1] * (-1)
Jun012015$D1[idx2] <- (Jun012015$D[idx2] * (-1)) + 360
Jun012015$D1[idx3] <- 0

I prefer this answer for people that don't grasp vectorization yet. It works and shouldn't be too much slower than mine (shown below). But I think it shows the process much more clearly and could help OP more in the future than mine which probably just looks like a mystery to somebody that is still using for loops and if statements. But here is my one-liner that should get it done:

Jun012015$D*(-1) + 360*(Jun012015$D > 0)

you would need to store that into a variable or overwrite Jun012015$D with it.

Dason
  • 60,663
  • 9
  • 131
  • 148
  • Wow, this is amazing. Thank you Dason for this very useful and straight forward solution. I was definitely over thinking it. – MKWalsh Jan 12 '16 at 18:45
  • @MKWalsh I wouldn't say you are overthinking it. It just seems like you're not quite used to working with things in a vectorized fashion yet. Eventually you'll come to a point where using for loops is fairly rare in your R programming. – Dason Jan 12 '16 at 18:46
  • 1
    Here's another suggestion that Docendo re-open his answer. "Fancy" arithmetic is fast and has its place, but his answer is more general and more readable. – Matthew Lundberg Jan 12 '16 at 20:27
  • @MatthewLundberg Agreed! – Dason Jan 12 '16 at 20:32
1

We could also use ifelse (but this will be considerably slower compared to @Dason's solution).

with(Jun012015, ifelse(D1 < 0, D1 * -1, ifelse(D1 > 0, D1 * -1 +360, 0)))

Or as @Dason suggested, a single ifelse can also fit into

with(Jun012015, ifelse(D1 <=0, D1 * -1, D1 * -1 + 360))

as 0 * (anynumber) = 0.

akrun
  • 874,273
  • 37
  • 540
  • 662
  • We could probably simplify to a single `ifelse` if you change the first comparison to `<=` instead of `<`. – Dason Jan 12 '16 at 18:40
  • @Dason Thanks, it is much nicer, but according to [here](http://stackoverflow.com/questions/34658775/find-and-replace-in-r-for-categorical-variables/34661155#34661155), doing some golfing got me negative votes. – akrun Jan 12 '16 at 18:42
  • I don't see any negative votes on that answer. Anyhow I'll be honest and say that I prefer your solution on that linked question to the ifelse solution. – Dason Jan 12 '16 at 18:45
-2

Try using ifelse rather than nested if else statements.

for(j in 1:n){
  ifelse(Jun012015$D[j] < 0, Jun012015$D[j]*(-1), 
         ifelse(Jun012015$D[j] > 0, (Jun012015$D[j] * (-1)) + 360, 0)
}

Please provide some sample data that you're running this loop on to help give benchmarked answers. The apply family of functions always work better than loops in R.

PrashanthVajjhala
  • 91
  • 1
  • 2
  • 11