#457Two-Sample Test + p-valueMedium

Two-Sample Test + p-value

Background

Every offline A/B decision lands on the same scalar: a pp-value from a two-sample test. The Welch / large-sample form is the workhorse — it does not assume equal variances between arms, which is the canonical L4 mistake of using a pooled Student-tt when the variances differ. For sample sizes typical of online experiments (thousands or more per arm) the normal approximation is exact enough that practitioners report a zz-statistic and a two-sided pp-value.

Problem statement

Implement two_sample_test(x, y) returning (z,p)(z, p) for the difference in means between two independent samples:

z  =  xˉyˉsx2/nx  +  sy2/ny,p  =  2(1Φ(z))z \;=\; \frac{\bar{x} - \bar{y}}{\sqrt{\,s_x^2/n_x \;+\; s_y^2/n_y\,}}, \qquad p \;=\; 2\bigl(1 - \Phi(|z|)\bigr)

where xˉ,yˉ\bar{x}, \bar{y} are the sample means, sx2,sy2s_x^2, s_y^2 are the sample variances (Bessel-corrected, divisor n1n - 1), and Φ\Phi is the standard-normal CDF.

Input

  • x - array-like of floats, sample from arm A. Must have 2\ge 2 elements.
  • y - array-like of floats, sample from arm B. Must have 2\ge 2 elements.

Output

  • (z, p) - tuple of plain Python floats. z may be negative; p lies in [0,1][0, 1] (two-sided).

Examples

Example 1 - clear separation between arms

Input:  x = [1, 2, 3, 4, 5], y = [6, 7, 8, 9, 10]
Output: (z, p) ~= (-5.0, 5.73e-7)

Explanation: xˉ=3\bar{x}=3, yˉ=8\bar{y}=8, sx2=sy2=2.5s_x^2=s_y^2=2.5, SE=0.5+0.5=1\text{SE} = \sqrt{0.5 + 0.5} = 1. z=(38)/1=5z = (3-8)/1 = -5. p=2(1Φ(5))5.73×107p = 2(1 - \Phi(5)) \approx 5.73 \times 10^{-7}.

Example 2 - identical samples

Input:  x = [1, 2, 3], y = [1, 2, 3]
Output: (0.0, 1.0)

Constraints

  • Use the sample variance (n1n - 1 in the denominator), not the population variance.
  • Two-sided pp-value: p=2(1Φ(z))p = 2(1 - \Phi(|z|)), computed from math.erf (Φ(z)=12(1+erf(z/2))\Phi(z) = \tfrac{1}{2}(1 + \mathrm{erf}(z/\sqrt{2}))).
  • Raise ValueError if either sample has fewer than 2 elements (sample variance undefined).
  • Tests use atol ~ 1e-6 on zz and rtol ~ 1e-3 on pp.

Notes

  • Why Welch's form (unpooled SE). Pooled-variance Student-tt assumes equal variances. In A/B-test data the variances of treatment and control differ routinely (a feature change that shifts watch-time means almost always shifts its variance too). Welch's form drops the assumption at no cost.
  • When the normal approximation breaks. For n< 30n < ~30 per arm, prefer the Welch-tt with its degrees-of-freedom approximation. At experimentation scale this is rarely the binding constraint.
Python
Loading...

▶ Run executes the 3 visible sample tests below in your browser. Submit runs the full suite — including hidden tests — on the server for an official verdict.

  • reference clear-separation case
  • example moderate overlap
  • sample with larger arrays