/
meanvar.go
76 lines (66 loc) · 1.39 KB
/
meanvar.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package main
import (
"math"
)
// MeanVar is for calculate mean and variance in the increment way.
type MeanVar struct {
N int // number of values.
M1 float64 // first moment.
Dev float64
NDev float64
M2 float64 // second moment.
BiasCorrected bool
}
// NewMeanVar return a new MeanVar.
func NewMeanVar() *MeanVar {
return &MeanVar{}
}
// Add adds a value.
func (m *MeanVar) Add(v float64) {
if m.N < 1 {
m.M1 = 0
m.M2 = 0
}
m.N++
n0 := m.N
m.Dev = v - m.M1
m.NDev = m.Dev / float64(n0)
m.M1 += m.NDev
m.M2 += float64(m.N-1) * m.Dev * m.NDev
}
// Mean returns the mean result.
func (m *MeanVar) Mean() float64 {
return m.M1
}
// Variance returns the variance.
func (m *MeanVar) Variance() float64 {
if m.N < 2 {
return math.NaN()
}
if m.BiasCorrected {
return m.M2 / float64(m.N-1)
}
return m.M2 / float64(m.N)
}
// Append add another result.
func (m *MeanVar) Append(m2 *MeanVar) {
if m.N == 0 {
m.N = m2.N
m.M1 = m2.M1
m.Dev = m2.Dev
m.NDev = m2.NDev
m.M2 = m2.M2
} else {
if m2.N > 0 {
total1 := m.M1 * float64(m.N)
total2 := m2.M1 * float64(m2.N)
newMean := (total1 + total2) / float64(m.N+m2.N)
delta1 := m.Mean() - newMean
delta2 := m2.Mean() - newMean
sm := (m.M2 + m2.M2) + float64(m.N)*delta1*delta1 + float64(m2.N)*delta2*delta2
m.M1 = newMean
m.M2 = sm
m.N = m.N + m2.N
}
}
}