/// <summary> /// Creates a new One-Sample Lilliefors' Kolmogorov-Smirnov test. /// </summary> /// /// <param name="sample">The sample we would like to test as belonging to the <paramref name="hypothesizedDistribution"/>.</param> /// <param name="hypothesizedDistribution">A fully specified distribution (which could have been estimated from the data).</param> /// <param name="alternate">The alternative hypothesis (research hypothesis) to test.</param> /// <param name="iterations">The number of Monte-Carlo iterations to perform. Default is 10,000.</param> /// <param name="reestimate">Whether the target distribution should be re-estimated from the sampled data /// at each Monte-Carlo iteration. Pass true in case <paramref name="hypothesizedDistribution"/> has been /// estimated from the data.</param> /// public LillieforsTest(double[] sample, ISampleableDistribution <double> hypothesizedDistribution, KolmogorovSmirnovTestHypothesis alternate = KolmogorovSmirnovTestHypothesis.SampleIsDifferent, int iterations = 10000, bool reestimate = true) : this() { if (reestimate) { if (!(hypothesizedDistribution is IFittableDistribution <double>)) { throw new InvalidOperationException("The estimate option can only be used with distributions that implement IFittableDistribution<double>."); } } this.Hypothesis = alternate; // Create a copy of the samples to prevent altering the // constructor's original arguments in the sorting step double[] orderedSamples = sample.Sorted(); // Create the theoretical and empirical distributions this.TheoreticalDistribution = hypothesizedDistribution; this.EmpiricalDistribution = new EmpiricalDistribution(orderedSamples, smoothing: 0); this.NumberOfSamples = sample.Length; StatisticDistribution = GetSimulatedDistribution(hypothesizedDistribution, reestimate, iterations, alternate); // Finally, compute the test statistic and perform actual testing. base.Statistic = KolmogorovSmirnovTest.GetStatistic(orderedSamples, TheoreticalDistribution, alternate); this.Tail = (DistributionTail)alternate; base.PValue = StatisticToPValue(Statistic); }
/// <summary> /// Creates a new One-Sample Kolmogorov test. /// </summary> /// /// <param name="sample">The sample we would like to test as belonging to the <paramref name="hypothesizedDistribution"/>.</param> /// <param name="hypothesizedDistribution">A fully specified distribution (which must NOT have been estimated from the data).</param> /// <param name="alternate">The alternative hypothesis (research hypothesis) to test.</param> /// public KolmogorovSmirnovTest(double[] sample, IDistribution <double> hypothesizedDistribution, KolmogorovSmirnovTestHypothesis alternate = KolmogorovSmirnovTestHypothesis.SampleIsDifferent) { this.Hypothesis = alternate; // Create the test statistic distribution with given degrees of freedom StatisticDistribution = new KolmogorovSmirnovDistribution(sample.Length); // Create a copy of the samples to prevent altering the // constructor's original arguments in the sorting step double[] sortedSamples = sample.Sorted(); // Create the theoretical and empirical distributions this.TheoreticalDistribution = hypothesizedDistribution; this.EmpiricalDistribution = new EmpiricalDistribution(sortedSamples, smoothing: 0); // Finally, compute the test statistic and perform actual testing. base.Statistic = GetStatistic(sortedSamples, TheoreticalDistribution, alternate); this.Tail = (DistributionTail)alternate; base.PValue = StatisticToPValue(Statistic); }
/// <summary> /// Gets the appropriate Kolmogorov-Sminorv D statistic for the samples and target distribution. /// </summary> /// /// <param name="sortedSamples">The sorted samples.</param> /// <param name="distribution">The target distribution.</param> /// <param name="alternate">The alternate hypothesis for the KS test. For <see cref="KolmogorovSmirnovTestHypothesis.SampleIsDifferent"/>, this /// is the two-sided Dn statistic; for <see cref="KolmogorovSmirnovTestHypothesis.SampleIsGreater"/> this is the one sided Dn+ statistic; /// and for <see cref="KolmogorovSmirnovTestHypothesis.SampleIsSmaller"/> this is the one sided Dn- statistic.</param> /// public static double GetStatistic(double[] sortedSamples, IDistribution <double> distribution, KolmogorovSmirnovTestHypothesis alternate) { // Finally, compute the test statistic and perform actual testing. switch (alternate) { case KolmogorovSmirnovTestHypothesis.SampleIsDifferent: return(TwoSide(sortedSamples, distribution)); case KolmogorovSmirnovTestHypothesis.SampleIsGreater: return(OneSideUpper(sortedSamples, distribution)); case KolmogorovSmirnovTestHypothesis.SampleIsSmaller: return(OneSideLower(sortedSamples, distribution)); } throw new ArgumentOutOfRangeException("alternate"); }
/// <summary> /// Creates a new One-Sample Kolmogorov test. /// </summary> /// /// <param name="sample">The sample we would like to test as belonging to the <paramref name="hypothesizedDistribution"/>.</param> /// <param name="hypothesizedDistribution">A fully specified distribution (which must NOT have been estimated from the data).</param> /// <param name="alternate">The alternative hypothesis (research hypothesis) to test.</param> /// public KolmogorovSmirnovTest(double[] sample, UnivariateContinuousDistribution hypothesizedDistribution, KolmogorovSmirnovTestHypothesis alternate = KolmogorovSmirnovTestHypothesis.SampleIsDifferent) { this.Hypothesis = alternate; double N = sample.Length; // Create the test statistic distribution with given degrees of freedom StatisticDistribution = new KolmogorovSmirnovDistribution(sample.Length); // Create a copy of the samples to prevent altering the // constructor's original arguments in the sorting step double[] Y = (double[])sample.Clone(); double[] D = new double[sample.Length]; // Sort sample Array.Sort(Y); // Create the theoretical and empirical distributions this.TheoreticalDistribution = hypothesizedDistribution; this.EmpiricalDistribution = new EmpiricalDistribution(Y, smoothing: 0); Func <double, double> F = TheoreticalDistribution.DistributionFunction; // Finally, compute the test statistic and perform actual testing. if (alternate == KolmogorovSmirnovTestHypothesis.SampleIsDifferent) { // Test if the sample's distribution is just significantly // "different" than the given theoretical distribution. // This is a correction on the common formulation found in many places // such as in Wikipedia. Please see the Engineering Statistics Handbook, // section "1.3.5.16. Kolmogorov-Smirnov Goodness-of-Fit Test" for more // details: http://www.itl.nist.gov/div898/handbook/eda/section3/eda35g.htm for (int i = 0; i < sample.Length; i++) { D[i] = Math.Max(Math.Abs(F(Y[i]) - i / N), Math.Abs((i + 1) / N - F(Y[i]))); } base.Statistic = D.Max(); // This is the two-sided "Dn" statistic. base.PValue = StatisticDistribution.ComplementaryDistributionFunction(Statistic); base.Tail = Testing.DistributionTail.TwoTail; } else if (alternate == KolmogorovSmirnovTestHypothesis.SampleIsGreater) { // Test if the sample's distribution is "larger" than the // given theoretical distribution, in a statistical sense. for (int i = 0; i < sample.Length; i++) { D[i] = Math.Max(i / N - F(Y[i]), (i + 1) / N - F(Y[i])); } base.Statistic = D.Max(); // This is the one-sided "Dn+" statistic. base.PValue = StatisticDistribution.OneSideDistributionFunction(Statistic); base.Tail = Testing.DistributionTail.OneUpper; } else { // Test if the sample's distribution is "smaller" than the // given theoretical distribution, in a statistical sense. for (int i = 0; i < sample.Length; i++) { D[i] = Math.Max(F(Y[i]) - i / N, F(Y[i]) - (i + 1) / N); } base.Statistic = D.Max(); // This is the one-sided "Dn-" statistic. base.PValue = StatisticDistribution.OneSideDistributionFunction(Statistic); base.Tail = Testing.DistributionTail.OneLower; } }
private EmpiricalDistribution GetSimulatedDistribution(ISampleableDistribution <double> hypothesizedDistribution, bool reestimate, int iterations, KolmogorovSmirnovTestHypothesis alternate) { double[] samples = new double[iterations]; if (reestimate) { Parallel.For(0, iterations, i => { double[] s = hypothesizedDistribution.Generate(samples: NumberOfSamples); Vector.Sort <double>(s); var fittable = (IFittableDistribution <double>)hypothesizedDistribution.Clone(); fittable.Fit(s); samples[i] = KolmogorovSmirnovTest.GetStatistic((double[])s, (IDistribution <double>)fittable, alternate); }); } else { Parallel.For(0, iterations, i => { double[] s = hypothesizedDistribution.Generate(samples: NumberOfSamples); Vector.Sort <double>(s); samples[i] = KolmogorovSmirnovTest.GetStatistic((double[])s, (IDistribution <double>)hypothesizedDistribution, alternate); }); } return(new EmpiricalDistribution(samples, smoothing: 0)); }