6

Averaging scalar wind direction data yields inaccurate values due to the compass headings ranging from 0-360 degrees, so I have converted my list to u and v components from the magnitude and wind direction angles already.

In order to back out the proper wind direction, for averaging purposes, I need to develop some sort of apply, ifelse, function for the 3 following scenarios:

V > 0...((180 / pi) * atan((Ucomp/Vcomp)) + 180)
U and V < 0...((180 / pi) * atan((Ucomp/Vcomp)) + 0)
U > 0 and V < 0...((180 / pi) * atan((Ucomp/Vcomp)) + 360)

In the data set I am looking to analyze, Ucomp is greater than 0 and Vcomp is less than zero, but there will undoubtedly be scenarios where all 3 will pan out, so I need a function to parse through and calculate iteratively and applying the correct formula for each time step. I have not used lapply or functions before, so me playing around with them has not worked.

I provide a sample of data below...

  DateTime Wind.Spd Wind.Direction Air.Density   Temp.C GEP.GE16XLE GCF.GE16XLE    Ucomp      Vcomp
1     1981 7.662370       248.3395   0.9148207 11.28967    597.7513    37.35946 5.253453 -0.7404972
2     1982 8.199412       251.6763   0.9172176 10.12751    678.8595    42.42872 5.867979 -0.6191475
3     1983 8.188782       251.7889   0.9162767 10.30619    667.9461    41.74663 5.777208 -1.0473982
4     1984 7.942632       246.7908   0.9174074 10.05093    642.6374    40.16484 5.415773 -0.6796723
5     1985 8.016558       252.7305   0.9171721 10.38414    654.2588    40.89117 5.649406 -0.9999082
6     1986 7.739984       249.6431   0.9158740 10.99859    607.0542    37.94089 5.305971 -0.9118965
RWJ
  • 389
  • 2
  • 6
  • 10

4 Answers4

8

You should look at using the atan2 function, it will probably remove the need for all the if statements and extra computing.

If you are doing a lot with directions then you should also look into the circular and CircStats packages which take care of a lot of these details for you (some is similar to what you did, just more automatic).

Greg Snow
  • 48,497
  • 6
  • 83
  • 110
7

Check out:

https://www.eol.ucar.edu/content/wind-direction-quick-reference

In short, you want to use atan2 to take care of the different quadrants, but don't forget that the angles are defined differently in meteorology! We measure the wind direction in degrees clockwise from North, whereas atan2-type functions generally work in radians from the X-direction (i.e. East). So you want to use something like:

WDIR= 270-atan2(V,U)*180/pi

Add a %360 to ensure the output is between 0 and 360:

WDIR= (270-atan2(V,U)*180/pi)%360

Thom Chubb
  • 509
  • 4
  • 10
7

First define the function to do the calculation:

windDir <- function(u, v) {
  if(v > 0)         ((180 / pi) * atan(u/v) + 180)
  if(u < 0 & v < 0) ((180 / pi) * atan(u/v) + 0)
  if(u > 0 & v < 0) ((180 / pi) * atan(u/v) + 360)
}

Then apply it to each row. Here I'm using ddply, which is a nice "apply" variety for data frames:

> library(plyr)
> ddply(data, 'DateTime', summarize, windDir=windDir(Ucomp, Vcomp))
  DateTime  windDir
1     1981 278.0232
2     1982 276.0232
3     1983 280.2760
4     1984 277.1531
5     1985 280.0370
6     1986 279.7517
John Colby
  • 22,169
  • 4
  • 57
  • 69
  • 1
    beautiful...thanks John...works perfectly. I have seen the plyr package in reading other forums, but have tried sticking with aggregate which works fine with scalars, but for this problem I needed something else. I was also monkeying with some elaborate if else statement that I couldnt quite figure out. I appreciate the help – RWJ Dec 29 '11 at 21:15
  • Im only doing it on monthly averaged data and yearly averaged data across 30 years, so it works fine for my purposes. – RWJ Dec 29 '11 at 22:27
  • See Greg Snow's comment: even without using `atan2`, in general you can save a lot of time and calculations with logical operations. E.g. for arbitrary functions `f`,`g` `y<- f(x)*sign(x) + (x==0) * g(x)` . The value of `y` for x <0 , x=0, x>0 is left as an exercise to the reader :-) – Carl Witthoft Dec 30 '11 at 14:53
  • Hi, I'm trying to use the winDir function, but I'm getting this output: `Error in if (u < 0 & v < 0) { : missing value where TRUE/FALSE needed`. I've got some NAs in my data frame so i added the following lines with no success `uNA<-is.na(u) vNA<-is.na(v) if(uNA=T) ("NA") if(vNA=T) ("NA")`. Any hint will be appreciated, Rafael – Rafael Jul 04 '13 at 06:29
4
windDir <- function(u, v) {
  (180 / pi) * atan(u/v) + ifelse(v>0,180,ifelse(u>0,360,0))
}