Stats mannwhitney test - CyrilB1531/lodestar GitHub Wiki
Development build. This page describes
main, not a released package. The latest published Lodestar.Stats is 0.4.0 โ read its documentation.
Home โบ Stats โบ Hypothesis tests
Compares two independent samples by their ranks.
public static TestResult Test(ReadOnlySpan<double> x, ReadOnlySpan<double> y, Alternative alternative = Alternative.TwoSided, Continuity continuity = Continuity.Applied, ExactMethod method = ExactMethod.Auto, NanPolicy nanPolicy = NanPolicy.Propagate)Parameters โ x and y are the two samples, each at least one value; both spans are read,
never modified. alternative says which tail the p-value covers. continuity says whether the
normal approximation gets the half-unit correction; it is ignored on the exact branch, where
there is nothing to approximate. method chooses the exact null distribution, its normal
approximation, or a choice between them by sample size and ties. nanPolicy says what to do with
a NaN; scipy's nan_policy, defaulting to NanPolicy.Propagate.
Returns โ TestResult: U for x, and the p-value.
Exceptions โ ArgumentException when either sample is empty, or nanPolicy is
NanPolicy.Raise and either sample holds a NaN. ArgumentOutOfRangeException when method
is ExactMethod.Exact and x.Length * y.Length exceeds 20,000.
Example โ a control group and a treated group, one value tied across them.
using Lodestar.Stats;
double[] control = [7.0, 3.0, 6.0, 2.0, 8.0, 5.0];
double[] treated = [9.0, 12.0, 8.0, 11.0, 15.0, 10.0];
TestResult result = MannWhitney.Test(control, treated);
double u = result.Statistic; // => 0.5
double p = Math.Round(result.PValue, 6); // => 0.006392Remarks โ control and treated share the value 8, so the pooled sample holds a tie and
ExactMethod.Auto falls straight to the normal approximation โ untied, both samples here are
small enough (six values each, at or under the eight-value bound Auto checks) that it would
have taken the exact route instead. Asking for ExactMethod.Exact explicitly still answers, just
not the same number: on this data it gives 0.004329 rather than 0.006392, because scipy
computes an exact p-value on tied data too instead of refusing, and this package matches that
rather than raising on a case scipy accepts.
Under NanPolicy.Propagate, a NaN reaches the statistic and the p-value. The check runs
before either sample is ranked โ unguarded, a NaN would sort to one end of its sample and take a
finite rank like any other value.
The exact route has a size bound Auto cannot cross. x.Length * y.Length above 20,000 costs
tens of seconds to enumerate โ the table is (m + 1) ร (nยทm + 1) and grows with the square of
that product. Passing ExactMethod.Exact past the bound throws; ExactMethod.Auto never does,
falling back to the asymptotic answer instead, because nothing the caller wrote asked for an
exact result. The bound on the smaller sample alone is eight, not both: x.Length = 8, y.Length = 10_000 still qualifies for Auto's exact route by that rule and would build a
multi-gigabyte table if the product bound did not also apply.
Applies to โ net10.0, netstandard2.0.
See also โ TTest.Independent for the parametric counterpart,
Wilcoxon.Paired for paired measurements,
ExactMethod, the Python equivalence table.