I have a weather station which measures both the direction and speed of the wind. It is connected to a SCADA system (TSX57xxx + Monitor Pro). Now I have a mathematical problem with calculating the average direction of the wind (my client needs the information for their reports). The problem is that the direction 0 degrees and 360 degrees are the same (the north, as You know...). Let's say that the wind is from the north; if I have e.g. 10 samples and half of them are 360 degrees and the other half are 0 degrees the result is 180 degrees! This is mathematically right result but... you know...it isn't!

Please help, I feel stupid...

Ville

(10 + 10 + 10 + 350) / 4 = 95 (incorrect)

((10 + 10 + 10 + 350) modulo 360) / 4 = 5 (correct)

Also - don't allow 360 as a valid reading. It aliases with 0 and is therefore ambiguous.

(90+90+90+90+90) modulo 360) / 5 = 18 (incorrect)

(90+90+90+90+90) / 5 = 90 (correct).

The method that you proposed doesn't work!

Then take the SIN of the Radians.

Next Average the SINs.

Now Take the inverse sin of the average.

Finally convert back to degrees.

Using EXCEL do this

Input directions in degrees say from cell A1 through A10.

in Cell B1 type -> Radians(A1)

in Cell C1 type -> SIN(B1)

in Cell A13 type -> Average(A1:A10)

in Cell A14 type -> ASIN(A13)

in Cell A15 type -> Degrees(A14)

Then if you would like to round to nearest five degrees you can

in Cell A16 type -> Mround(A15,5)

>Then take the SIN of the Radians.

>Next Average the SINs.

>Now Take the inverse sin of the

>average.

>Finally convert back to degrees.

The solution is again so simple, only to figure it out... thanks!

moin all,

for angles the mathematics work slightly different as usual (angles do not belong to the body of real numbers.)

Angles are in the one side open range [0..360), i.e. including 0 but excluding 360 and above. While building the sum of all measured angles subtract 360 until the result is in that range.

Sample: 2 times 350 degrees and 1 time 20 degrees. The sum will hold

1. 350

2. 700, which will be reduced to 340

3. 360, which will be reduced to 0

finally divide by 3.

If you have the mod function available, you could simply sum all angles and finally calc the remainder mod 360 before you divide by the number of measured values.

Regards

Friedrich Haase

Ing.-Büro Dr. Friedrich Haase

Consulting - Automatisierungstechnik

email Friedrich@61131.com

WEB http://www.61131.com

((100+100+100+100)modulo 360) / 4 = 10 (incorrect, should be 100).

Here is a solution that really will work. For each angle sampled, accumulate the sum of the sines and the sum of the cosines. Then divide each of these sums by the number of entries to get:

x = average cosine

y = average sine

Then use the arctan2 function to get the average angle as:

Angle = arctan2( y , x);

Note that it is still possible to get an indeterminate answer if x=0 and y=0, as would be the case when trying to average 90 and 270. There is no solution to that problem anyway. Finally, you might want to weight the averages with the wind velocity. A wind angle of 10 degrees at 20 knots averaged with a wind angle of 20 degrees at 3 knots should probably not be 15 degrees. The angle when the wind was at 20 knots is probably more important than the angle when the wind was almost calm. So they should not be averaged together without some unequal weighting.

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

Convert the wind direction and speed into a vector, sum them up, then divide by the number of samples.

However, the trigonometric algorithm is itself not a general solution, as it may produce an average direction which the instrument never at any time pointed to or passed through. For example consider the following set of direction readings (taken in sequence) 120, 120, 120, 90, 0, 0, 270, 240, 240, 240. We can see the wind gradually shifted from 120 degrees to 240 degrees, while passing through 0 degrees. It would seem reasonable that the "average" in this case is 0 degrees. We can also see that the wind did in fact blow at 0 degrees, at one point.

The trigonometric solution though produces a result of 180 degrees, even though the wind never in fact blew in that direction at any time. It would appear that the path taken to travel between points is as important as the readings themselves.

The modulo solution is not incorrect, it is simply incomplete as it does not cover all cases. Admittedly, this distinction is probably of little interest to most people.

There is however, another approach which is probably simpler than the modulo version, but also does not require trigonometric functions (which are not always available). Unless I am mistaken, I believe there are two cases. One case is where the line which connects the extreme and all intermediate values passes through zero, and the other case is where it does not.

Where the line passes through zero, the values to the "right" of zero (e.g. 359, 358, 357, etc.) could be converted to negative angles (e.g. 359 would be -1, 358 would be -2, etc.). If the average is negative, this would then be corrected to a positive angle by adding 360 again.

Where the line does not pass through zero, this step would be unecessary. In either case, a simple mathematical average could be used as there is no longer a numerical discontinuity. The objective in either case is to produce a single continuous scale describing the path actually taken.

Determining whether the line passes through zero is an exercise that is left for the student.

179,179,179,179,179,10,195,181,181,181,181,181

If your purpose in forming the average is to determine where to place a windscreen to protect a rose bush, I would say something near is 180 is best. But your method would have me place the windscreen on exactly the wrong side.

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

If the wind is sampled every 5 minutes, then averaging the reading via a simple formula is pointless. If the readings are intended for use in weather prediction, then the appropriate source to be consulted on this should be a

meteorologist, not the Automation List. Meteorologists no doubt have standard measurement and analysis techniques to address these questions in a manner which is consistant with readings taken elsewhere. We could come up with dozens of clever algorithms, but none of them are of much use if they don't follow the conventions used in collecting weather data.

As for protecting your rose bushes, the normal means to do this is to wrap them completely in burlap for the winter, is it not? Knowing the average is of little use in the exception.

Hi.

There seems to have been rather a lot of wide-ranging discussion already on this topic (I've also learnt something about gardening too, which is a bonus).

I've done something like this before, and used a vector based approach. As you have a SCADA system, it is straightforward to build two analog calculation tags, say WindX and WindY, which represent the X and Y component of the wind magnitude and direction. These two tags should be historized, so that it is easy to extract the 1 hour average or 8 hour average or whatever you need for the report.

WindX = Magnitude*COS(2*3.1416*(90-Direction)/360)

WindY = Magnitude*SIN(2*3.1416*(90-Direction)/360)

The convention for X and Y is standard rectangular coordinates, ie X = East, Y = North

Once you've got the X and Y values being historized, the average wind strength and direction can be calculated by getting the average of X and Y over the required period.

You then need to convert back to compass-based co-ordinates. The following VBA script (part of a macro in a spreadsheet) does this:

'---------------------

Sub WindCalculations()

'---------------------

'

Dim nRow As Long, nCol As Long

Dim rAlpha As Single ' Angle, polar coordinates

Dim rBeta As Single ' Angle, from North

Dim x As Double, y As Double

Dim rVal As Double

For nRow = 2 To 18

x = Cells(nRow, 5) ' Column E, WindX

y = Cells(nRow, 6) ' Column F, WindY

' Magnitude

' ---------

Cells(nRow, 8) = Sqr(x * x + y * y)

' Calculate polar coordinate angle

' --------------------------------

If x = 0 Then

If y > 0 Then

rAlpha = 90

ElseIf y < 0 Then

rAlpha = -90

Else

rAlpha = 0

End If

Else

rVal = y / x

If x > 0 And y > 0 Then

rAlpha = 180 / 3.14159265358979 * Atn(rVal)

ElseIf x < 0 And y < 0 Then

rAlpha = 180 + 180 / 3.14159265358979 * Atn(rVal)

ElseIf x > 0 And y < 0 Then

rAlpha = 180 / 3.14159265358979 * Atn(rVal)

Else

' x < 0 and y > 0

rAlpha = -180 + 180 / 3.14159265358979 * Atn(rVal)

End If

End If

Cells(nRow, 9) = rAlpha

' Convert to compass bearing

' --------------------------

rBeta = 90 - rAlpha

If rBeta < 0 Then

rBeta = rBeta + 360

End If

Cells(nRow, 10) = rBeta

Next nRow

End Sub

--- End of WindCalcs ---

This VBA code forms part of a macro in a spreadsheet, which can be downloaded from my web site:

http://www.procdev.com/downloads/windcalcs.zip

Hope that helps you out. Now I'd better get back to my regular job...

Chris D<br>

http://www.procdev.com

http://www.webmet.com/met_monitoring/621.html

Compliments of the Canadian Weather Service.

Bob Pawley

1. Find the average and standard deviation of the given numbers.

2. Increase the smallest number by 360.

3. Repeat steps 1 and 2 until all numbers are greater than 360.

4. Choose the average that yields the smallest standard deviation.

5. If the average is greater than 360 then subtract 360.

I have posted a longer explanation at http://polytope.com/average-angle.txt

--

Romeli

Electrical engineer

PT.Smelting

Affiliate of Mitsubishi Materials

phone: 62-31-3976464 fax: 62-31-3976466

www.smelting.co.id

In first step, you should calculate sum of sin(theta) and cos (theta), where theta is your wind direction. In second step take atan2[sum(sin(theta),sum(cos(theta)]), represents the average wind direction. But the answer is positively defined, however this type of wind direction traditionally does not used in meteorology, since 0 (or 360) indicates Northly but in mathematics it is 90 degree; hence you should convert to meteorological wind directions.

Dr. Hasan TATLI (Canakkale Onsekiz Mart University, Dept. of Geography, Turkey)

Sorry to disrupt the party, but I'm pretty sure most answers to this posting are not correct.

Averaging x,y-directions, sines of angles... (e.g. obtained after atan()-calls) is bound to fail because it will produce biased results.

What should be done is computing the first eigen-vector of the direction covariance-matrix. Here is how to do it:

1. Stack all n directions (normalised wind-vectors) in an (n x 2)-matrix M (i.e. 1 direction per row).

2. Compute the direction covariance matrix as follows:

C = M' * M

where M' is the transpose of M and * is the regular matrix-product. C should now be a (2 x 2)-matrix.

3. Compute the first eigen-vector of this matrix. This is the dominant direction.

Notice that this procedure does not take the magnitude of each direction into account, i.e. the dominant direction is not biased towards the direction(s) with largest wind-magnitude. If you also want to take this into account, just omit the normalisation of wind-vectors when computing C.

Kind regards,

Rik

I tried some examples using your eigen-vector method and using the method I proposed:

atan2(sum of sines, sum of cosines)

and I got the same answer. Can you give a simple example where the eigen-vector method gives a different result from mine? (See my posting above in this thread).

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

Is there a difference in methods for real-time processing (while the data is collected) and post-processing (after the data is collected) to calculate average? I checked the sensor documentation and it says it uses vector components to calculate real-time averages? What about using software that come with the weather station? I know it will generate average too. Any suggestion will be highly appreciated.

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

IMO, Bob Peterson has the best solution (and it's one of the simplest approaches, too).

But I would probably tweak his approach...

Because the only problem with his solution is that 1/2 hour of wind due north at 50 mph followed by 1/2 hour of wind due south at 50 mph would yield an average wind velocity of 0 mph. I'm guessing you would probably prefer the average value to equal 50 mph.

What I would do is this...

To computer average direction, convert each direction sample into a UNITY vector and add them up and divide by the number of samples.

To obtain the average velocity, add together the absolute value of all the velocity samples and divide by the number of samples.

Hope this helps!

Averaging unity direction vectors can also be misleading. Suppose the wind is nearly calm for much of the day, but when it blows hard, it always blows from the West (270 degrees). But when the wind is nearly calm, it is mostly from the East (090 degrees). All those easterly unity vectors will overwhelm the westerly ones. I'm not sure you want to give such weight to vectors that were nearly zero in magnitude.

Aldous:

The website you cited:

http://www.webmet.com/met_monitoring/62.html

confirms the method that I outlined in my 20 May 2005 posting above.

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

http://www.webmet.com/met_monitoring/62.html

Aldous

Can you tell me if it works correctly for your problem?

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

static float angle_0to360(float theta)

{

int k = (int)(theta / 360);

theta = theta - k * 360;

if (theta < 0) {

theta = theta + 360;

}

return theta;

}

static float new_angle_mean(float old_theta, float new_theta, int old_num)

{

float mean_theta;

float dtheta;

if (old_theta == new_theta) {

return old_theta;

}

dtheta = fabsf(old_theta - new_theta);

if (dtheta > 180) {

old_theta = (old_theta > 180) ? old_theta - 360: old_theta;

new_theta = (new_theta > 180) ? new_theta - 360: new_theta;

}

mean_theta = (old_theta*old_num + new_theta) / (old_num + 1.);

return angle_0to360(mean_theta);

}

int main()

{

int i, num;

float *theta;

float mean_theta = 0.;

printf("give number of angles: ");

scanf("%d", &num);

theta = malloc(num * sizeof(float));

printf("give %d angles: ", num);

for (i = 0; i < num; i++) {

scanf("%f", θ[i]);

theta[i] = angle_0to360(theta[i]);

mean_theta = new_angle_mean(mean_theta, theta[i], i);

}

printf("\nmean_theta = %f\n\n", mean_theta);

free(theta);

}

angle______"mean" so far

4 _____ 4

180 _____ 92

270 _____ 151.3

340 _____ 108.5

270 _____ 140.8

330 _____ 112.3

300 _____ 87.7

260 _____ 109.2

300 _____ 90.4

If you plot these angles, you will agree that the average ought to be somewhere around 270 degrees, not 90.4. I can clearly keep extending the list using angles that are all close to 270 and still make your "average" stay around 90. As I and several others have said earlier, you have to average the sines and cosines and then take are arctangent.

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

I´m following your example mentioned above (20 May 2005). In the case we would work with the negative values (359 = -1; 358 = -2, etc) where could we find the limit to this negative values? I mean that if we have 179 and -179 for example (in the situation that South=180 were the limit) the average is 0=N when should be 180=S.

So where could we find the limit to estimate the real average? Have you got some suggestion?

Thank you very much.

Julian

Uppsala Universitet

>...So where could we find the limit to estimate the real average? Have you got some suggestion?<

My suggestion is the same as before (see my earlier postings). Stop trying to average the angles directly and average the sines and cosines instead. It is the only way that actually works in all situations.

Robert Scott

Real-Time Specialties

Embedded Systems Consulting

Try to trap 360 value and output it as 0 so to make your average correct. Just add the following logic :

value = X "data acquired"

If value = 360 then value = 0 else value = X

"Then use "value" as your data element for the degrees or wind direction then you're OK.

randy

% Develop a total wind vector to determine average heading. This eliminates any problems with averaging values like [5,355,-180,180]

N = sum(MG .* cosd(HD));

E = sum(MG .* sind(HD));

Ave_MG = mean(MG);

Ave_HD = atan2(E,N) * cR2D;

http://stackoverflow.com/questions/491738/how-do-you-calculate-the- average-of-a-set-of-angles/3651941#3651941

Try this with excel:

For realvector averaging:

Put windspeed and winddirection data in column A and B.

Then calculate the components of wind (u and v are in column C and D):

=-A1*SIN(PI()/180*B1)

=-A1*COS(PI()/180*B1)

In column E and F (for example,if you have 60 data in one hour) calculate the average of the components of wind:

=AVERAGE(c1:c60)

=AVERAGE(d1:d60)

Column G is the average value of the windspeed:

=SQRT(e1*e1+f1*f1))

Column H is the average value of the winddirection:

=IF(e1=0;(IF(f1=0;0;IF(f1>0;360;180)));IF(e1>0;(270-180/PI()* ATAN(f1/e1));(90-180/PI()*ATAN(f1/e1))))

For unitvector averaging:

column C and D:

=-SIN(PI()/180*B1)

=-COS(PI()/180*B1)

column E and F:

=AVERAGE(c1:c60)

=AVERAGE(d1:d60)

column G:

=average(a1:a60)

column H:

=IF(e1=0;(IF(f1=0;0;IF(f1>0;360;180)));IF(e1>0;(270-180/PI()* ATAN(f1/e1));(90-180/PI()*ATAN(f1/e1))))

Hope this helps.

M.A.Saghafi

Meteorology Specialist (M.Sc)

Tehran University

Here's an different but very easy solution. I searched for myself a way to have daily averages of my hourly measured wind direction data. I found that there is no excellent and %100 correct solution. Therefore I make my own method to have a most represanting daily direction. My way will give you not the exact average value of the measured degrees, but you will have the most dominated daily wind direction.

1) Convert you degree data to direction codes. Here is the formula for excel:

=IF(B1<=22;"1";IF(B1<=67;"2";IF(B1<=11 2;"3";IF(B1<=157;"4";IF(B1<=202;"5";I F(B1<=247;"6";IF(B1<=292;"7";IF(B1<337;" ;8";"1"))))))))

1= N, 2=NE, 3=E, 4=SE, 5=S, 6=SW, 7=W, 8=NW

2)Calculate the most frequent value (in excel: MODE) for each day.

That's all.

Cemil Seyis

TUBITAK MRC, Turkey

=IF(e1=0;(IF(f1=0;0;IF(f1>0;360;180)));IF(e1>0;(270-180/PI()* ATAN(f1/e1));(90-180/PI()*ATAN(f1/e1))))

=IF(e1=0,(IF(f1=0,"n/a",IF(f1>0;360;0))),IF(e1>0,(2 70-180/PI()*ATAN(f1/e1)),(90-180/PI()*ATAN(f1/e1))))

> =IF(e1=0,(IF(f1=0,"n/a",IF(f1>0;360;0))),IF(e1>0,(270- 180/PI()*ATAN(f1/e1)),(90-180/PI()*ATAN(f1/e1))))

This is a very simple mathematical and meteorological issue (actually page 2 of "Meteorology for Scientists and Engineers" by Roland B Stull..

Note: time period can be any time period (this example is hourly)

*** Matlab code below

For each ten minute wind speed measurement the u- and the v-component of the wind need to be calculated in order to average wind direction.

u-comp ws = -1 * (ws*sin(wd*PI/180))

v-comp ws = -1 * (ws*cos(wd*PI/180))

where PI = 3.1415926535897

assuming six 10-minute values in an hour

average the six u-comp WS and six v-comp WS to get an average u-comp and v-comp for the hour

if average u-comp > 0

hourly average WD = (90-180/PI*atan(average v-comp/average u-comp)+180)

elseif average u-comp < 0

hourly average WD = (90-180/PI*atan(average v-comp/average u-comp))

elseif average u-comp = 0

if average v-comp < 0

hourly average WD = 360

elseif average v-comp > 0

hourly average WD = 180

else

hourly average WD = 0

end

end

Example Calculation:

Six WS measurements: [2.3, 2.7, 4.5, 5.2, 10.3, 8.1]

Six WD measurements: [220, 174, 43, 356, 99, 67]

Results:

Average u-comp = -3.18989225

Average v-comp = -0.930826755

Hourly Average WD = 73.73 degrees

Hourly Average WS = 5.5167 m/s

just wondering why there is -1 in calculating the U and V components?

Thanks

Jy

So, here's what I got to work for me using a couple columns of logic (no radians, sin or vector required):

A1:A10 = Raw Data

B1: =IF(A1>180,A1-360,A1) <drag down to B10

C2: =IF(ABS(A1-A2)>180,1,"") <drag down to C10

D10: =IF(SUM(C1:C10)>0,IF(AVERAGE(B1:B10)<0,360+AVERAGE(B1:B10),AVERA GE(B1:B10)),AVERAGE(A1:A10))

Seen all the replies to this post. If anyone is still interested the following VB6 code {function) works a treat.

Basically we convert all wind directions into their rectangular co-ordinates. Next we sum and average the vertical and horizontal components and from these averages we use the ArcTan function {Atn in vb} to work out the horizontal angle of the average wind. Knowing the sense {+ve \-ve} of the horizontal & vertical components we can establish in which of the 4 quadrants the wind vector is and convert the horizontal angle to a 0~359deg wind angle.

I have tested his code and it works fine across all quadrants giving accurate results.

Public Function AverageWind(CSV_WindString$)

'__________________________________________________________________ _____________________________________________

'__ This Function takes a CSV string of wind direction values in the range 0 ~ 259 degrees and

' returns the mean wind direction in degrees [0 ~ 359] as a numerical value {i.e. NOT a string!}

' Example of CSV_WindString$ = "170, 170, 190, 190"... this returns 180 as an average numerical value

'__________________________________________________________________ _____________________________________________

Wind = CSV_WindString$

p = 0

n = 0 ' Count of number of wind direction values to be averaged

pi = 22 / 7

Do ' Primary Loop to 1. extract individual wind directions and 2. to calculate their rectangular components then 3. to Average them out

'__ Get each wind direction value in turn

n = n + 1

p = InStr(Wind, ",")

If p > 0 Then

Wdir = Val(Mid$(Wind, 1, p - 1))

Wind = Trim$(Mid$(Wind, p + 1))

Else

Wdir = Val(Wind)

End If

'__ Compute Horizontal and vertical components

If Wdir >= 0 And Wdir < 90 Then Qd = 1

If Wdir >= 90 And Wdir < 180 Then Qd = 2

If Wdir >= 180 And Wdir < 270 Then Qd = 3

If Wdir >= 270 And Wdir < 360 Then Qd = 4

Select Case Qd

Case Is = 1 ' a+jb

Ang = 90 - Wdir ' Angle w.r.t. Horizontal {E\W} axis

angR = pi * Ang / 180

Case Is = 2 ' a-jb

Ang = Wdir - 90 ' Angle w.r.t. Horizontal {E\W} axis

angR = pi * Ang / 180

Case Is = 3 ' -a-jb

Ang = 270 - Wdir ' Angle w.r.t. Horizontal {E\W} axis

angR = pi * Ang / 180

Case Is = 4 ' -a+jb

Ang = Wdir - 270 ' Angle w.r.t. Horizontal {E\W} axis

angR = pi * Ang / 180

End Select

a = Cos(angR) ' Horizontal component of wind vector

b = Sin(angR) ' Vertical component of wind vector

'__ Correct Quadrant Signage of the wind vector's horizontal [a] & vertical [b] components

Select Case Qd

Case Is = 1 ' All [a&b] +ve

a = a

b = b

Case Is = 2 ' Horizontal [a] +ve, Vertical [b] -ve

a = a

b = -b

Case Is = 3 ' Both [a&b] -ve

a = -a

b = -b

Case Is = 4 ' Horizontal [a] -ve; Vertical [b] +ve

a = -a

b = b

End Select

'__ Calculate Cumulative values of horizontal [CuA] and vertical [CuB] components of wind angles

CuA = CuA + a ' Cumulative sum of all the horizontal components of each wind vector being averaged.

CuB = CuB + b ' Cumulative sum of all the vertical components of each wind vector being averaged.

'__Prevent division by zero in event of either value being exactly zero

If CuA = 0 Then CuA = 0.0000001

Loop While p <> 0 ' END of primary loop

'__ Calculate resulting horizontal angle [Ang] of cumulative sums of vertical and horizontal components of all wind vectors

Ang = Int(180 * (Atn(Abs(CuB / n) / Abs(CuA / n))) / pi + 0.5)

'__ As [Ang] if the horizontal angle relative to the E\W axis of the wind rose, the wind direction is calculated from

' the Quadrant indicated by the signage of components CuA and CuB as below:-

If CuA > 0 And CuB > 0 Then WindDir = 90 - Ang: Q = 1 ' i.e. Both CuA & CuB are +ve indicating Quadrant #1

If CuA > 0 And CuB < 0 Then WindDir = 90 + Ang: Q = 2 ' i.e. CuA is +ve & CuB is -ve indicating Quadrant #2

If CuA < 0 And CuB < 0 Then WindDir = 270 - Ang: Q = 3 ' i.e. Both CuA & CuB are -ve indicating Quadrant #3

If CuA < 0 And CuB > 0 Then WindDir = 270 + Ang: Q = 4 ' i.e. CuA is -ve & CuB is +ve indicating Quadrant #4

If WindDir = 360 Then WindDir = 0 ' Occasionally the above code returns WindDir as 360. This corrects it to zero!

Quadrant = Q ' Not used in Function ~ For Tracking info only!

AverageWind = WindDir

End Function

Users of this site are benefiting from open source technologies, including PHP, MySQL and Apache. Be happy.

**Fortune**

Larkinson's Law:

All laws are basically false.