stat: add circular standard deviation#2011
Conversation
| // CircularStdDev returns the circular standard deviation of the dataset. | ||
| // | ||
| // sqrt(-2 * log(sqrt((\sum_i w_i * sin(alpha_i))^2 + (\sum_i w_i * cos(alpha_i))^2) / length(x))) | ||
| func CircularStdDev(x []float64) float64 { |
There was a problem hiding this comment.
Our stat functions take weights. Please add this.
There was a problem hiding this comment.
Unfortunately I am neither a data scientist nor a statistician, and I don't know how to (correctly) implement a weighted circular standard deviation. I also didn't find a reference implementation in R or scipy — or, crucially, a reference implementation to use to generate test cases.
If you can provide any pointers I'll be happy to add it.
There was a problem hiding this comment.
There is https://rdrr.io/github/matthewkling/windscape/src/R/circ_sd.R, but I don't have the expertise to adapt it into this implementation.
There was a problem hiding this comment.
Blunt. Needs tests.
func CircularStdDev(x []float64, weights []float64) float64 {
if weights != nil && len(x) != len(weights) {
panic("stat: slice length mismatch")
}
var aX, aY float64
if weights != nil {
var sumW float64
for i, v := range x {
w := weights[i]
sumW += w
aX += w * math.Cos(v)
aY += w * math.Sin(v)
}
return math.Sqrt(-2 * math.Log(math.Hypot(aY, aX)/sumW))
} else {
for _, v := range x {
aX += math.Cos(v)
aY += math.Sin(v)
}
return math.Sqrt(-2 * math.Log(math.Hypot(aY, aX)/float64(len(x))))
}
}
There was a problem hiding this comment.
Thank you for your help, @kortschak.
3bf72c7 implements weighted circular standard deviation and adds some test cases, the output of which I've validated against astropy's circstats library.
Co-authored-by: Dan Kortschak <dan@kortschak.io>
This PR adds a new function,
CircularStdDev, togonum/statalongside the existingCircularMean.Checklist:
linked to relevant issues(n/a)