Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Classical Testbossanova EquivalentData Transformation
One-sample t-testmodel("y ~ 1", df)None (raw data)
Wilcoxon signed-rankmodel("signed_rank(y) ~ 1", df)sign(x) * rank(abs(x))

One-Sample t-test

Classical:

t=xˉμ0s/n,tt(n1) under H0t = \frac{\bar{x} - \mu_0}{s / \sqrt{n}}, \quad t \sim t(n - 1) \text{ under } H_0

As GLM:

yiN(μ,σ2),μ=β0y_i \sim \mathcal{N}(\mu, \sigma^2), \quad \mu = \beta_0

t=β^0SE(β^0)t(n1) under H0:β0=0t = \frac{\hat{\beta}_0}{\text{SE}(\hat{\beta}_0)} \sim t(n-1) \text{ under } H_0: \beta_0 = 0

The classical tt and the GLM tt are identical — fitting an intercept-only Gaussian GLM with identity link recovers the one-sample t-test exactly.

scipy

from scipy.stats import ttest_1samp

scipy_ttest = ttest_1samp(penguins['bill_length_mm'].to_numpy(), 0)
scipy_ttest
TtestResult(statistic=np.float64(148.77670538724365), pvalue=np.float64(3.211394152836e-312), df=np.int64(341))

bossanova

m = model("bill_length_mm ~ 1", penguins).fit().infer()

m.params.select("statistic", "df", "p_value")
Loading...

Wilcoxon Signed-Rank Test

Classical:

W=i=1nRi+sign(xi),z=Wn(n+1)/4n(n+1)(2n+1)/24˙N(0,1) under H0W = \sum_{i=1}^{n} R_i^+ \cdot \text{sign}(x_i), \quad z = \frac{W - n(n+1)/4}{\sqrt{n(n+1)(2n+1)/24}} \dot{\sim} \mathcal{N}(0,1) \text{ under } H_0

As GLM:

yiN(μ,σ2),μ=β0,where yi=sign(yi)rank(yi)y_i^* \sim \mathcal{N}(\mu, \sigma^2), \quad \mu = \beta_0, \quad \text{where } y_i^* = \text{sign}(y_i) \cdot \text{rank}(|y_i|)

t=β^0SE(β^0)t(n1) under H0:β0=0t = \frac{\hat{\beta}_0}{\text{SE}(\hat{\beta}_0)} \sim t(n-1) \text{ under } H_0: \beta_0 = 0

The signed-rank transformation makes inference robust to outliers. The GLM approach replaces the WW statistic with a tt-test on signed ranks — both test the same null hypothesis of zero location.

scipy

from scipy.stats import wilcoxon

scipy_wilcox = wilcoxon(penguins['bill_length_mm'].to_numpy(), mode='approx')
scipy_wilcox
WilcoxonResult(statistic=np.float64(0.0), pvalue=np.float64(8.218085850268946e-58))

bossanova

m_wilcox = model("signed_rank(bill_length_mm) ~ 1", penguins).fit().infer()

m_wilcox.params.select("statistic", "p_value")
Loading...

scipy reports the Wilcoxon W statistic; bossanova reports a t-statistic on signed ranks. The test statistics differ but both test H₀: location = 0 and yield equivalent p-values.