1package stats
2
3import "math"
4
5// Quartiles holds the three quartile points
6type Quartiles struct {
7	Q1 float64
8	Q2 float64
9	Q3 float64
10}
11
12// Quartile returns the three quartile points from a slice of data
13func Quartile(input Float64Data) (Quartiles, error) {
14
15	il := input.Len()
16	if il == 0 {
17		return Quartiles{}, EmptyInput
18	}
19
20	// Start by sorting a copy of the slice
21	copy := sortedCopy(input)
22
23	// Find the cutoff places depeding on if
24	// the input slice length is even or odd
25	var c1 int
26	var c2 int
27	if il%2 == 0 {
28		c1 = il / 2
29		c2 = il / 2
30	} else {
31		c1 = (il - 1) / 2
32		c2 = c1 + 1
33	}
34
35	// Find the Medians with the cutoff points
36	Q1, _ := Median(copy[:c1])
37	Q2, _ := Median(copy)
38	Q3, _ := Median(copy[c2:])
39
40	return Quartiles{Q1, Q2, Q3}, nil
41
42}
43
44// InterQuartileRange finds the range between Q1 and Q3
45func InterQuartileRange(input Float64Data) (float64, error) {
46	if input.Len() == 0 {
47		return math.NaN(), EmptyInput
48	}
49	qs, _ := Quartile(input)
50	iqr := qs.Q3 - qs.Q1
51	return iqr, nil
52}
53
54// Midhinge finds the average of the first and third quartiles
55func Midhinge(input Float64Data) (float64, error) {
56	if input.Len() == 0 {
57		return math.NaN(), EmptyInput
58	}
59	qs, _ := Quartile(input)
60	mh := (qs.Q1 + qs.Q3) / 2
61	return mh, nil
62}
63
64// Trimean finds the average of the median and the midhinge
65func Trimean(input Float64Data) (float64, error) {
66	if input.Len() == 0 {
67		return math.NaN(), EmptyInput
68	}
69
70	c := sortedCopy(input)
71	q, _ := Quartile(c)
72
73	return (q.Q1 + (q.Q2 * 2) + q.Q3) / 4, nil
74}
75