How to Perform Welch's t-Test in Python
Calculate the Welch t-statistic and degrees of freedom for two samples with unequal variances using Python's statistics module.
Python code
28 linesimport math
from statistics import mean, variance
def welch_t_test(sample1, sample2):
n1, n2 = len(sample1), len(sample2)
mean1, mean2 = mean(sample1), mean(sample2)
var1, var2 = variance(sample1), variance(sample2)
# Welch's t statistic
t_stat = (mean1 - mean2) / math.sqrt(var1 / n1 + var2 / n2)
# Welch–Satterthwaite degrees of freedom
df_num = (var1 / n1 + var2 / n2) ** 2
df_den = ((var1 / n1) ** 2) / (n1 - 1) + ((var2 / n2) ** 2) / (n2 - 1)
df = df_num / df_den
return t_stat, df
if __name__ == "__main__":
# Mock data: two groups with unequal variances
group_a = [5.1, 6.2, 5.4, 6.8, 5.9, 6.1]
group_b = [8.5, 7.9, 8.2, 7.5, 8.0, 7.8, 8.4]
t_statistic, degrees_freedom = welch_t_test(group_a, group_b)
print(f"t-statistic: {t_statistic:.4f}")
print(f"degrees of freedom: {degrees_freedom:.4f}")
Output
t-statistic: -6.0439
degrees of freedom: 10.3700
How it works
Welch's t-test adapts Student's t-test for samples with unequal variances and unequal sizes. The t-statistic uses each sample's variance divided by its own size, avoiding the pooled variance assumption. The degrees of freedom are computed with the Welch–Satterthwaite equation, which can be fractional. This function returns only the statistic and degrees of freedom; to get a p-value you must use the cumulative distribution function from scipy.stats.t or the scipy.stats.ttest_ind function with equal_var=False.
Common mistakes
- Using the pooled variance formula instead of Welch's when variances differ.
- Forgetting that `statistics.variance` uses Bessel's correction (sample variance, not population).
- Assuming degrees of freedom will be an integer; it can be fractional.
- Not accounting for unequal sample sizes when computing degrees of freedom.
Variations
- Use `scipy.stats.ttest_ind(sample1, sample2, equal_var=False)` to get the p-value directly.
- Compute the p-value with `scipy.stats.t.sf(abs(t_stat), df) * 2` for a two-tailed test.
Real-world use cases
- Comparing conversion rates between a control and a new feature when sample sizes and variances differ.
- A/B testing two pricing models where user traffic and response variability are not equal.
- Evaluating model performance metrics (e.g., latency) across two server clusters with different loads.
Sponsored
More from A/B testing & experimentation
Keep learning
Related tutorials and quizzes for this topic.