diff --git a/deviation.go b/deviation.go index e69a19f..f5e8695 100644 --- a/deviation.go +++ b/deviation.go @@ -1,6 +1,8 @@ package stats -import "math" +import ( + "math" +) // MedianAbsoluteDeviation finds the median of the absolute deviations from the dataset median func MedianAbsoluteDeviation(input Float64Data) (mad float64, err error) { @@ -55,3 +57,29 @@ func StandardDeviationSample(input Float64Data) (sdev float64, err error) { // Return the sample standard deviation return math.Sqrt(vs), nil } + +// StandardDeviationUnion finds the new Standard deviation of an array +// when you are appending new elemnts (without processing former elements) +func StandardDeviationUnion(input Float64Data, formerMean float64, formerLength int, formerSD float64) (sdev float64, err error) { + + if input.Len() == 0 { + return math.NaN(), EmptyInputErr + } + inputMean, _ := Mean(input) + UnionMean := ((float64(formerLength) * formerMean) + (float64(len(input)) * inputMean)) / float64((len(input) + formerLength)) + C := UnionMean / formerMean + elem1 := formerSD * formerSD + formerMeanPow2 := formerMean * formerMean + elem2 := (C*C - 1) * formerMeanPow2 + elem3 := (1 - C) * 2 * formerMeanPow2 + elem4 := 0.0 + + for _, n := range input { + elem4 += (n - UnionMean) * (n - UnionMean) + } + elem4 /= float64(formerLength) + + UnionVariance := float64(formerLength) / float64(formerLength+len(input)) * (elem1 + elem2 + elem3 + elem4) + // Return the sample standard deviation + return math.Sqrt(UnionVariance), nil +} diff --git a/examples/main.go b/examples/main.go index afdbd0c..59b693d 100644 --- a/examples/main.go +++ b/examples/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "time" "github.com/montanaflynn/stats" ) @@ -189,4 +190,21 @@ func main() { description, _ := stats.Describe([]float64{1.0, 2.0, 3.0}, true, &[]float64{25.0, 50.0, 75.0}) fmt.Println(description.String(2)) + + dt1 := []float64{1, 3, 423, 4235, 342, 5, 123, 124, 23, 432, 543, 5, 346} + dt2 := []float64{6} + dt3 := append(dt1, dt2...) + dt1Mean, _ := stats.Mean(dt1) + SD1, _ := stats.StandardDeviation(dt1) + t1 := time.Now() + SD3, _ := stats.StandardDeviation(dt3) + t1Diff := time.Now().Sub(t1) + t1End := time.Now() + SD3New, _ := stats.StandardDeviationUnion(dt2, dt1Mean, len(dt1), SD1) + t2Diff := time.Now().Sub(t1End) + + fmt.Printf("StandardDeviation took : %v\n", t1Diff) + fmt.Printf("StandardDeviationUnion took : %v\n", t2Diff) + fmt.Printf("StandardDeviation: %v\n", SD3) + fmt.Printf("StandardDeviationUnion : %v\n", SD3New) }