75 lines
1.5 KiB
Go
75 lines
1.5 KiB
Go
|
package stats
|
||
|
|
||
|
import "math"
|
||
|
|
||
|
// Quartiles holds the three quartile points
|
||
|
type Quartiles struct {
|
||
|
Q1 float64
|
||
|
Q2 float64
|
||
|
Q3 float64
|
||
|
}
|
||
|
|
||
|
// Quartile returns the three quartile points from a slice of data
|
||
|
func Quartile(input Float64Data) (Quartiles, error) {
|
||
|
|
||
|
il := input.Len()
|
||
|
if il == 0 {
|
||
|
return Quartiles{}, EmptyInput
|
||
|
}
|
||
|
|
||
|
// Start by sorting a copy of the slice
|
||
|
copy := sortedCopy(input)
|
||
|
|
||
|
// Find the cutoff places depeding on if
|
||
|
// the input slice length is even or odd
|
||
|
var c1 int
|
||
|
var c2 int
|
||
|
if il%2 == 0 {
|
||
|
c1 = il / 2
|
||
|
c2 = il / 2
|
||
|
} else {
|
||
|
c1 = (il - 1) / 2
|
||
|
c2 = c1 + 1
|
||
|
}
|
||
|
|
||
|
// Find the Medians with the cutoff points
|
||
|
Q1, _ := Median(copy[:c1])
|
||
|
Q2, _ := Median(copy)
|
||
|
Q3, _ := Median(copy[c2:])
|
||
|
|
||
|
return Quartiles{Q1, Q2, Q3}, nil
|
||
|
|
||
|
}
|
||
|
|
||
|
// InterQuartileRange finds the range between Q1 and Q3
|
||
|
func InterQuartileRange(input Float64Data) (float64, error) {
|
||
|
if input.Len() == 0 {
|
||
|
return math.NaN(), EmptyInput
|
||
|
}
|
||
|
qs, _ := Quartile(input)
|
||
|
iqr := qs.Q3 - qs.Q1
|
||
|
return iqr, nil
|
||
|
}
|
||
|
|
||
|
// Midhinge finds the average of the first and third quartiles
|
||
|
func Midhinge(input Float64Data) (float64, error) {
|
||
|
if input.Len() == 0 {
|
||
|
return math.NaN(), EmptyInput
|
||
|
}
|
||
|
qs, _ := Quartile(input)
|
||
|
mh := (qs.Q1 + qs.Q3) / 2
|
||
|
return mh, nil
|
||
|
}
|
||
|
|
||
|
// Trimean finds the average of the median and the midhinge
|
||
|
func Trimean(input Float64Data) (float64, error) {
|
||
|
if input.Len() == 0 {
|
||
|
return math.NaN(), EmptyInput
|
||
|
}
|
||
|
|
||
|
c := sortedCopy(input)
|
||
|
q, _ := Quartile(c)
|
||
|
|
||
|
return (q.Q1 + (q.Q2 * 2) + q.Q3) / 4, nil
|
||
|
}
|