Disparity(x + c, y + c) = Disparity(x, y)Disparity(kx, ky) = Disparity(x, y)
Disparity expresses a difference between groups in a way that does not depend on the original measurement units. A disparity of 0.5 means the groups differ by half a spread unit; 1.0 means one full spread unit. Being dimensionless allows comparison of effect sizes across different studies, metrics, or measurement scales. What counts as a large or small disparity depends entirely on the domain and what matters practically in a given application. Do not rely on universal thresholds; interpret the number in context.
Algorithm
The Disparity estimator is a composition of Shift and Spread:
Disparity(x,y)=Shift(x,y)/AvgSpread(x,y)
where AvgSpread(x,y)=(n⋅Spread(x)+m⋅Spread(y))/(n+m) is the pooled scale.
The algorithm proceeds as follows:
Compute Spread for each sample Delegate to the Spread algorithm for x and y independently.
Compute AvgSpread Form the weighted average AvgSpread=(n⋅Spread(x)+m⋅Spread(y))/(n+m).
Domain check Verify that AvgSpread>0. If the pooled spread is zero, the division is undefined.
Compute Shift Delegate to the Shift algorithm for the pair (x,y).
Divide Return Shift(x,y)/AvgSpread(x,y).
using Pragmastat.Algorithms;using Pragmastat.Exceptions;using Pragmastat.Internal;using Pragmastat.Metrology;namespace Pragmastat.Estimators;public class DisparityEstimator : ITwoSampleEstimator{ public static readonly DisparityEstimator Instance = new(); public Measurement Estimate(Sample x, Sample y) { Assertion.NonWeighted("x", x); Assertion.NonWeighted("y", y); Assertion.CompatibleUnits(x, y); (x, y) = Assertion.ConvertToFiner(x, y); var spreadX = FastSpread.Estimate(x.SortedValues, isSorted: true); if (spreadX <= 0) throw AssumptionException.Sparity(Subject.X); var spreadY = FastSpread.Estimate(y.SortedValues, isSorted: true); if (spreadY <= 0) throw AssumptionException.Sparity(Subject.Y); var shiftVal = FastShift.Estimate(x.SortedValues, y.SortedValues, [0.5], true)[0]; var avgSpreadVal = (x.Size * spreadX + y.Size * spreadY) / (x.Size + y.Size); return (shiftVal / avgSpreadVal).WithUnit(MeasurementUnit.Disparity); }}
Tests
Disparity(x,y)=Shift(x,y)/AvgSpread(x,y)
The Disparity test suite contains 30 test cases (16 original + 12 unsorted + 2 error). Since Disparity combines Shift and AvgSpread, unsorted tests verify both components handle sorting correctly.
Demo examples (n=m=5) — from manual introduction, validating properties:
The smaller test set for Disparity reflects implementation confidence. Since Disparity combines Shift and AvgSpread, correct implementation of those components ensures Disparity correctness. The test cases validate the division operation and confirm scale-free properties.
unsorted-anti-symmetry-unsorted: x=(8,0,4,2,6), y=(12,0,6,3,9) (demo-4 reversed and unsorted)
As a composite estimator, Disparity tests both the numerator (Shift) and denominator (AvgSpread). Unsorted variants verify end-to-end correctness including invariance properties.
Error cases — input validation (2 tests):
error-empty-x: x=(), y=(1,2,3,4,5) — empty X array violates validity
error-empty-y: x=(1,2,3,4,5), y=() — empty Y array violates validity
References
Statistical Power Analysis for the Behavioral Sciences