package onlinestats import "math" type Stats interface { Mean() float64 Var() float64 Len() int } // Welch implements a Welch's t-test. Returns the probability that the difference in means is due to chance. func Welch(xs, ys Stats) float64 { xvar := xs.Var() yvar := ys.Var() xn := float64(xs.Len()) yn := float64(ys.Len()) wvar := (xvar/xn + yvar/yn) vnum := wvar * wvar vdenom := (xvar*xvar)/(xn*xn*(xn-1)) + (yvar*yvar)/(yn*yn*(yn-1)) // both have 0 variance, the difference is the difference of the means var v float64 if vdenom == 0 { v = xn + yn - 2 } else { v = vnum / vdenom } // if the variances are 0, we return if the means are different if wvar == 0 { if math.Abs(ys.Mean()-xs.Mean()) > 0.0000000001 { return 1 } else { return 0 } } t := (ys.Mean() - xs.Mean()) / math.Sqrt(wvar) return pt(t, v) } // translated from https://bitbucket.org/petermr/euclid-dev/src/9936542c1f30/src/main/java/org/xmlcml/euclid/Univariate.java func pt(t, df float64) float64 { // ALGORITHM AS 3 APPL. STATIST. (1968) VOL.17, P.189 // Computes P(T= 2 { for k = ks; k <= im2; k += 2 { c = c * b * (fk - 1) / fk s += c if s != idf { idf = s fk += 2 } } } if ioe != 1 { return 0.5 + 0.5*a*math.Sqrt(b)*s } if df == 1 { s = 0 } return 0.5 + (a*b*s+math.Atan(a))*g1 }