My goal is to calculate a mean and standard deviation for a series of compass degrees. Since I may cross the 360/ 0 mark, I can't use the a standard mean or sd calculation.
I've been using the circular packing in R, which seems to give me the correct means (though negative values are used when crossing the 360 mark as opposed to positive). But the sd values are way too small. Any thoughts on what might be wrong, or a better way to calculate mean and sd for compass directions?
The below code is my attempt to test my calculations of mean and sd on various compass directions, and compare to a standard mean and sd calculation (they should agree unless I cross the 360/ 0 mark)
library(circular)
Tester<-c(20,40,60)
Tester<-c(340,360,20)
Tester<-c(340,0,20)
Tester<-c(300,320,340)
Tester<-c(160,180,200)
ToCirc<- circular(Tester, type="angles", units="degrees",rotation="clock")
mean(ToCirc)
sd(ToCirc)
mean(Tester)
sd(Tester)
When you load circular
, it has a separate sd
function that calculates standard deviation for circular data differently.
#DATA
Tester<-c(160,180,200)
ToCirc<- circular(Tester, type="angles", units="degrees",rotation="clock")
sd(ToCirc)
#[1] 0.2864803
#The above is equivalent to
r = rho.circular(ToCirc) #Resultant Length
sqrt(-2*log(r)) #Then sd
#[1] 0.2864803
If you want to use the sd
of base after loading circular
, use sd.default
sd.default(ToCirc)
#[1] 20
#which is equal to
sd.default(Tester)
#[1] 20
OR calculate everything yourself
Tester<-c(340,360,20)
sine = sum(sin(Tester * pi/180)) #sin of each angle, convert to radian first
cosine = sum(cos(Tester * pi/180)) #cos of each angle, convert to radian first
Tester_mean = (atan2(sine, cosine) * 180/pi) %% 360
mu = (Tester - Tester_mean + 180) %% 360 - 180 #Difference of each angle from mean
Tester_sd = sqrt(sum(mu^2)/(length(Tester) - 1)) #Standard Deviation
Tester_mean
#[1] 0
Tester_sd
#[1] 20