*! version 1.0.0 23dec2025

Title

wasstest -- Two-sample Wasserstein Distance test for equality of distributions

Syntax

wasstest
varname [if] [in] , "by(varlist:groupvar)"
[,
reps(#)
seed(#)
power(#)]

groupvar must take on
two distinct values. The distribution of varname for the first value of
groupvar is compared with that of the second value.

* "by(varlist:groupvar)" specify a binary variable that identifies the two groups

reps(#) perform # Monte Carlo permutations; default is reps(1000)

seed(#) set random-number seed to #

power(#) specify the exponent for the Wasserstein statistic; default is power(1)

* Required

Description

wasstest performs a two-sample Wasserstein distance permutation test
to assess whether two samples come from the same distribution. The
Wasserstein distance (also known as Earth Mover's Distance) measures
the minimum "work" required to transform one distribution into another.
Unlike Cramer-von Mises and Anderson-Darling tests which focus on
vertical differences between CDFs, the Wasserstein distance considers
both vertical differences and the horizontal distances between points,
making it sensitive to both location and spread differences. The permutation
test provides an exact p-value by comparing the observed statistic to its
distribution under random reassignment of group labels.

Options

"by(varlist:groupvar)" is required. It specifies a binary variable
that identifies the two groups.

reps(#) specifies the number of random permutations for the test;
the default is reps(1000).

seed(#) sets the random-number seed for reproducible results.

power(#) specifies the exponent for the Wasserstein statistic calculation;
the default is power(1) which gives the standard Wasserstein distance (Earth Mover's
Distance), measuring the minimum "work" to transform one distribution into another.
power(>1) gives more weight to large vertical discrepancies between distributions.
power(<1) gives more balanced weighting, reducing the relative importance of large discrepancies.

Examples

Set-up

. clear

. set obs 20

. gen group = cond(_n < 11,1,2)

. gen x = runiform() in 1/10

. replace x = runiform() * 1.30 if group==2

wasstest using defaults

. wasstest x, by(group)

wasstest with specific seed and more permutations

. wasstest x, by(group) reps(2000) seed(12345)

change exponent to cubed weighting

. wasstest x, by(group) reps(2000) seed(12345) power(3)

Stored results

wasstest stores the following in r():

Scalars

r(stat) observed Wasserstein statistic

r(p) permutation p-value

r(reps) number of permutations performed

r(power) power parameter specified

Macros

r(group1) name of group 1

r(group2) name of group 2

References

Villani, C. 2009.
Optimal Transport: Old and New.
Springer.

Ramdas, A., Garcia, N., and Cuturi, M. 2017.
On Wasserstein two-sample testing and related families of nonparametric tests.
Entropy
19: 47.

Citation of wasstest

wasstest is not an official Stata command. It is a free contribution
to the research community, like a paper. Please cite it as such:

Linden A. (2025). WASSTEST: Stata module to perform a two-sample Wasserstein Distance test for equality of distributions

Author

Ariel Linden

President, Linden Consulting Group, LLC

alinden@lindenconsulting.org

Also see

ksmirnov, ranksum, permute, cvmtest (if installed), adtest (if installed) escftest (if installed), distcomp (if installed)