/// <summary> /// Checks that (x-y) > threshold /// </summary> /// <remarks>Should be consistent with t.test(x, y, mu=threshold, alternative="greater") from R</remarks> public WelchResult IsGreater(double[] x, double[] y, Threshold threshold = null) => IsGreater(new Statistics(x), new Statistics(y), threshold);
public OneSidedTestResult(double pValue, Threshold threshold) { PValue = pValue; Threshold = threshold; }
public TostResult(Threshold threshold, EquivalenceTestConclusion conclusion, [CanBeNull] T slowerTestResult, [CanBeNull] T fasterTestResult) : base(threshold, conclusion) { SlowerTestResult = slowerTestResult; FasterTestResult = fasterTestResult; }
/// <summary> /// Checks that (x-y) > threshold /// </summary> /// <remarks>Should be consistent with wilcox.test(x, y, mu=threshold, alternative="greater") from R</remarks> public MannWhitneyResult IsGreater(double[] x, double[] y, Threshold threshold = null) { threshold = threshold ?? RelativeThreshold.Default; double thresholdValue = threshold.GetValue(new Statistics(x)); int n = x.Length, m = y.Length; if (Math.Min(n, m) < 3 || Math.Max(n, m) < 5) { return(null); // Test can't be applied } var xy = new double[n + m]; for (int i = 0; i < n; i++) { xy[i] = x[i]; } for (int i = 0; i < m; i++) { xy[n + i] = y[i] + thresholdValue; } var index = new int[n + m]; for (int i = 0; i < n + m; i++) { index[i] = i; } Array.Sort(index, (i, j) => xy[i].CompareTo(xy[j])); var ranks = new double[n + m]; for (int i = 0; i < n + m;) { int j = i; while (j + 1 < n + m && Math.Abs(xy[index[j + 1]] - xy[index[i]]) < 1e-9) { j++; } double rank = (i + j + 2) / 2.0; for (int k = i; k <= j; k++) { ranks[k] = rank; } i = j + 1; } double ux = 0; for (int i = 0; i < n + m; i++) { if (index[i] < n) { ux += ranks[i]; } } ux -= n * (n + 1) / 2.0; double uy = n * m - ux; if (n <= SmallN && m <= SmallN) { double pValue = 1 - PValueForSmallN(n, m, ux - 1); return(new MannWhitneyResult(ux, uy, pValue, threshold)); } else { double mu = n * m / 2.0; double su = Math.Sqrt(n * m * (n + m + 1) / 12.0); double z = (ux - mu) / su; double pValue = 1 - MathHelper.Gauss(z); return(new MannWhitneyResult(ux, uy, pValue, threshold)); } }
/// <summary> /// Two-one-sided t-tests /// </summary> public static TostResult <T> CalculateTost <T>(IOneSidedTest <T> test, double[] baseline, double[] candidate, Threshold threshold) where T : OneSidedTestResult { if (baseline.SequenceEqual(candidate)) // WelchTest would throw StackoverflowException ;) { return(new TostResult <T>(threshold, EquivalenceTestConclusion.Base, null, null)); } var fasterTestResult = test.IsGreater(baseline, candidate, threshold); var slowerTestResult = test.IsGreater(candidate, baseline, threshold); EquivalenceTestConclusion conclusion; if (fasterTestResult == null || slowerTestResult == null) { conclusion = EquivalenceTestConclusion.Unknown; } else if (fasterTestResult.NullHypothesisIsRejected) { conclusion = EquivalenceTestConclusion.Faster; } else if (slowerTestResult.NullHypothesisIsRejected) { conclusion = EquivalenceTestConclusion.Slower; } else { conclusion = EquivalenceTestConclusion.Same; } return(new TostResult <T>(threshold, conclusion, slowerTestResult, fasterTestResult)); }
/// <summary> /// Determines whether the sample mean is different from a known mean /// </summary> /// <remarks>Should be consistent with t.test(x, mu = mu, alternative = "greater") from R </remarks> public OneSidedTestResult IsGreater(double[] sample, double value, Threshold threshold = null) => IsGreater(new Statistics(sample), value, threshold);