Learn · Part B · Chapter 7

Two independent means

Did the new portal get people paying sooner? Welch's t test by default, and when pooling is justified.

Two samples pulling apart: Helion's days to payment as the customers come in
Playback speed

Two rows of dots show days to payment for customers on the old portal and on Portal v2, with each group's mean marked. Below, a curve shows how much the difference in means would wobble from sample to sample at the current size: its centre is the observed difference, a vertical line marks zero, and a bar marks the 95 % interval. At each step more customers join both groups, from 4 per group up to all 12,000. With few customers the curve is wide and straddles zero; as the groups grow it narrows and moves clear of zero, ending at a difference of −1.09 days, t = −17.35, interval −1.21 to −0.97 days.

What you just saw

Helion Energy, a European energy retailer, rebuilt its self-service billing portal and randomised 12,000 customers between the old portal and the new one, Portal v2, for one billing cycle. One of finance's questions: do customers on Portal v2 pay their bills sooner? Days from bill to payment tie up working capital, so a day matters.

The animation let the customers in a few at a time, in random order. With 4 per group the difference in mean days to payment was −1.58 days, but the curve showing how much such a difference wobbles was so wide that it straddled zero comfortably. At 15 per group the difference even pointed the wrong way, +0.26 days. That is what small samples do. As the groups grew, the curve narrowed, moved clear of zero and settled on the answer from all 12,000: Portal v2's customers paid 1.09 days sooner, with a 95 % interval from −1.21 to −0.97 days.

Two things moved the verdict: the size of the gap, which barely changed once the groups had a few hundred customers each, and the width of the curve, which kept shrinking as n grew. The test statistic is their ratio.

The two-sample t statistic

The two-sample t test compares the means of two separate, unrelated groups: control against treatment, region A against region B. Its statistic has the same shape as every other: the signal, the gap between the two sample means, over the noise, the standard error of that gap.

In words: \(\bar{x}_1\) and \(\bar{x}_2\) are the two groups' means, \(s_1\) and \(s_2\) their standard deviations, and \(n_1\) and \(n_2\) their sizes. Each group's mean wobbles by \(s/\sqrt{n}\); the gap between two independent means wobbles by the square root of the sum of their squares. For Helion, with Portal v2 as group 1 (6,031 customers, mean 14.355 days, s = 3.40) and the old portal as group 2 (5,969 customers, mean 15.445 days, s = 3.48):

The gap is more than 17 standard errors from zero. If the portal made no difference, a gap like this would essentially never happen: p = 1.3 × 10⁻⁶⁶.

Welch's t test, by default

The formula above is Welch's t test. The classic Student version differs in one respect: it assumes the two groups have the same variance, pools the two standard deviations into one, and uses n₁ + n₂ − 2 degrees of freedom:

Just use Welch's t test The classic Student t test assumes the two groups have equal variances. Welch's version does not, and it is essentially as powerful when the variances are equal. So there is no situation in which testing for equal variances first and then choosing is better than simply always using Welch. In SciPy that means equal_var=False, and it should be your default. (SciPy's default is True: one of the few places where the library's default is not the recommended practice.)

For Helion the choice hardly matters: the pooled test also gives t = −17.35, because the groups are nearly the same size and their spreads are close. It matters when a small group has the larger spread. The animation below runs 1,000 experiments in which the two populations have the same mean, so every rejection is a false alarm: 10 values with a standard deviation of 20 against 40 values with a standard deviation of 5.

Pooled against Welch: 1,000 experiments where the means are equal but the spreads are not
Playback speed

Each experiment compares a group of 10 with a standard deviation of 20 against a group of 40 with a standard deviation of 5, drawn from populations with the same mean, so every rejection is a false alarm. Two bars fill as the experiments run: the share rejected by the pooled t test and the share rejected by Welch's t test, against a dashed line at the promised 5 %. The pooled test's bar climbs far past the line; Welch's settles on it.

The pooled test rejected 311 times in 1,000, a false-alarm rate of 31.1 % where it promised 5 %: pooling lets the 40 calm values speak for the 10 wild ones, so its standard error comes out far too small. Welch's test rejected 48 times, 4.8 %, as promised.

Why this is true: Why Welch's degrees of freedom are not a whole number

Welch's standard error adds two estimated variances, and each is uncertain in its own way. The sum wobbles like a variance with some number of degrees of freedom between the smaller group's n − 1 and n₁ + n₂ − 2, and a formula named after Welch and Satterthwaite finds that number from the data (below).

Each group's term, \(s^2/n\), counts in proportion to how much of the total uncertainty it carries. For Helion both terms are about the same size, so the degrees of freedom come out at about 11,986, close to the pooled 11,998. With 10 wild values against 40 calm ones they fall close to 9, the small group's own, which is exactly the caution the pooled test lacks.

The assumptions, and what the checks decide

The two-sample t test assumes independence within and between the groups (one row per customer; randomisation takes care of the rest), approximately normal sampling distributions of the two means, and, for the pooled version only, equal variances. Helion's analysis checks each before running the test:

The assumption checks for Helion's days to payment
CheckResultWhat it means
Levene's test of equal variancesW = 1.23, p = 0.267The spreads are comparable
Skewness of days to payment0.795: skewed to the right, as billing data usually areThe data are not normal, but the mean of about 6,000 values is: the central limit theorem works on the mean
Group sizes5,969 and 6,031Ample

Welch's test is used regardless of Levene's result: it is valid whether the variances are equal or not, and costs almost nothing when they are. Running Levene first and switching to the pooled test when it does not reject is exactly the habit the callout above rules out.

The result, and how big it is

Helion's H2: Welch's two-sample t test on days to payment
QuantityValue
Old portal, mean days to payment15.44 days (5,969 customers)
Portal v2, mean days to payment14.36 days (6,031 customers)
Difference, Portal v2 minus old−1.09 days
Welch's t−17.35, df ≈ 11,986
p-value1.3 × 10⁻⁶⁶
95 % interval for the difference−1.21 to −0.97 days
Cohen's d−0.32, small to medium
Mann–Whitney checkp = 5.2 × 10⁻⁷⁰, the same direction

The effect size for two groups is Cohen's d: the gap divided by the pooled standard deviation, 3.44 days, so d = −0.32. Here the effect is both statistically overwhelming and practically meaningful: about a day off the working-capital cycle, with an interval tight enough that the size is not in doubt.

The Mann–Whitney test is there because a reviewer will ask whether the mean is the right summary for skewed billing data. It compares the two groups without assuming normality (chapter 14), and it rejects too, in the same direction: Portal v2's customers tend to pay sooner. Being able to say that both tests agree closes that line of challenge before it opens, and the lab says it only because both results say so.

Why it matters

A retailer with millions of customers counts working capital in days: paying a day sooner across the book is real money, and the interval says the gain is at least 0.97 days. Choosing Welch by default means the decision never rests on an assumption about equal spreads that nobody checked, and the robustness check means it does not rest on the mean alone.

When this goes wrong

Independence is the assumption no test can check. If the same customer appeared twice, or if customers were randomised in households or regions rather than one by one, the effective sample would be smaller than the row count and every standard error too small. In small samples of skewed data the t test's normal approximation fails too, and the mean may not be the question anyway: chapter 14's rank and permutation tests are the alternatives. And a pooled test with a small, noisy group can raise six times the false alarms it promises, as the animation showed.

In code

What it computes Python (scipy, statsmodels) Excel
Welch's t test, the sensible default ttest_ind(treatment, control, equal_var=False) =T.TEST(B2:B6032, C2:C5970, 2, 3)
The pooled (Student) test, for comparison ttest_ind(treatment, control, equal_var=True) =T.TEST(B2:B6032, C2:C5970, 2, 2)
Levene's test, median-centred, if you want to report it levene(treatment, control, center='median') =F.DIST.RT(W, 1, 11998)
Cohen's d with the pooled standard deviation (treatment.mean() - control.mean()) / np.sqrt(((n1-1)*v1 + (n2-1)*v2) / (n1+n2-2)) =(AVERAGE(B2:B6032)-AVERAGE(C2:C5970))/SQRT(((6031-1)*VAR.S(B2:B6032)+(5969-1)*VAR.S(C2:C5970))/(6031+5969-2))
The Mann–Whitney check mannwhitneyu(treatment, control) =RANK.AVG(B2, $B$2:$C$12001)

ttest_ind, levene and mannwhitneyu are in scipy.stats. Excel's T.TEST returns the p-value only: its last argument 3 is Welch, 2 is pooled. Excel has no Levene or Mann–Whitney test: W comes from an ANOVA on the absolute deviations from each group's median, and the Mann–Whitney route starts from the ranks (chapter 14).

Try this Run Helion's days to payment in the two-means explorer, then switch between Welch's test and the pooled test and watch the degrees of freedom.
Try this Play the pooled-against-Welch run again and step through its first 50 experiments: watch how often the pooled test cries wolf.
Try this Watch the two samples pull apart once more, and stop at 15 customers per group, where the gap pointed the wrong way.
Remember: To compare two independent means, use Welch's t test by default: the gap between the means over the standard error of the gap, √(s₁²/n₁ + s₂²/n₂). Report the difference with its interval and Cohen's d beside the p-value. Helion's Portal v2 customers paid 1.09 days sooner, 95 % interval 0.97 to 1.21 days.

Practise

4 exercises

Quiz

Three questions on the chapter. Your best score is kept in this browser.

1. When should you use the pooled (Student) t test instead of Welch's?
2. What is the standard error of the gap between two independent means?
3. In the animation, a group of 10 with a large spread met a group of 40 with a small one. What happened to the pooled test?
Answer every question first.
Means, proportions and counts · step 4 of 10

Pooled against Welch

A small noisy group against a large calm one, 1,000 times with no real difference. The pooled test cries wolf far more than 5 % of the time; Welch's holds. Ask why a Levene pre-test is not the fix: it decides too late and too weakly.

All steps
An unhandled error has occurred. Reload 🗙

Reconnecting…

Your connection to Hypothesis Testing Lab dropped, probably a Wi-Fi blip. Hold on while it reconnects.

The connection could not be restored. The page will reload in a few seconds.