Tests t pour comparer des moyennes
Effectuez des tests t à un échantillon, à deux échantillons indépendants et appariés avec scipy.stats, puis interprétez les intervalles de confiance.
Tests t pour comparer des moyennes est une leçon Pandas & NumPy Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Pandas & NumPy Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Pandas & NumPy Academy comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
What Is a T-Test?
A t-test is a hypothesis test that determines whether a difference in means between groups is statistically significant or likely due to random chance. It compares the observed difference to the variability in the data, producing a t-statistic and a p-value. If p ≤ 0.05 (the conventional threshold), we reject the null hypothesis that the means are equal. There are three common types: one-sample, independent two-sample, and paired t-test, each for different experimental designs.
One-Sample T-Test
The one-sample t-test tests whether the mean of a sample differs significantly from a known or hypothesised population mean. For example: 'Is our average delivery time significantly different from the industry standard of 3 days?' Use scipy.stats.ttest_1samp(data, popmean). The null hypothesis is H₀: mean = popmean. A small p-value leads you to reject H₀ and conclude the sample mean differs from the target.
import numpy as np
from scipy import stats
np.random.seed(42)
# Delivery times in days (true mean is ~3.5, not 3)
delivery_times = np.random.normal(loc=3.5, scale=0.8, size=50)
# Test: is our mean significantly different from 3 days?
stat, p = stats.ttest_1samp(delivery_times, popmean=3.0)
print(f'Sample mean: {delivery_times.mean():.3f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Differs from 3?', 'Yes' if p < 0.05 else 'No')Independent Two-Sample T-Test
The independent two-sample t-test compares the means of two independent groups. For example: 'Does the A/B test variant produce higher average revenue than the control?' Use scipy.stats.ttest_ind(group_a, group_b). The equal_var parameter matters: set equal_var=False (Welch's t-test) when the two groups may have different variances, which is the safe default for most real data.
import numpy as np
from scipy import stats
np.random.seed(0)
# A/B test revenue per session
control = np.random.normal(loc=25.0, scale=8.0, size=80)
variant = np.random.normal(loc=28.0, scale=9.0, size=80)
# Welch's t-test (does not assume equal variances)
stat, p = stats.ttest_ind(control, variant, equal_var=False)
print(f'Control mean: {control.mean():.2f}')
print(f'Variant mean: {variant.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Significant difference?', 'Yes' if p < 0.05 else 'No')One-Tailed vs Two-Tailed Tests
By default, t-tests are two-tailed: they test whether means differ in either direction (greater OR less than). If you have a directional hypothesis ('the variant increases revenue'), use a one-tailed test with the alternative parameter: 'greater' or 'less'. A one-tailed test has more power for the specific direction but provides no evidence about the other direction. Decide on the direction before looking at the data to avoid HARKing (Hypothesising After Results are Known).
import numpy as np
from scipy import stats
np.random.seed(1)
control = np.random.normal(25, 8, 100)
variant = np.random.normal(27, 8, 100)
# Two-tailed (default): does mean differ at all?
stat, p_two = stats.ttest_ind(control, variant, equal_var=False,
alternative='two-sided')
# One-tailed: is variant > control?
stat, p_one = stats.ttest_ind(control, variant, equal_var=False,
alternative='less')
print(f'Two-tailed p: {p_two:.4f}')
print(f'One-tailed p (variant greater): {p_one:.4f}')Paired T-Test
The paired t-test is used when each observation in group A has a natural partner in group B — for example, measurements before and after a treatment on the same subjects, or the same stores in two different months. Pairing controls for between-subject variability, making the test more powerful than an independent t-test for the same data. Use scipy.stats.ttest_rel(before, after). The order of elements must be matched: before[i] and after[i] must come from the same subject.
import numpy as np
from scipy import stats
np.random.seed(5)
# Blood pressure before and after medication (paired)
before = np.random.normal(130, 10, 30)
after = before - np.random.normal(5, 3, 30) # Treatment reduces BP by ~5
stat, p = stats.ttest_rel(before, after)
print(f'Mean before: {before.mean():.2f}')
print(f'Mean after: {after.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Treatment effective?', 'Yes' if p < 0.05 else 'No')Interpreting the T-Statistic
The t-statistic measures how many standard errors the observed difference is from zero. A t-statistic of 2 means the observed difference is 2 standard errors above what would be expected under the null. For a two-tailed test at α=0.05 with a large sample, the critical value is approximately ±1.96 — so |t| > 1.96 gives p < 0.05. The p-value converts the t-statistic to a probability, making it easier to interpret without consulting t-distribution tables.
import numpy as np
from scipy import stats
# Demonstrate relationship between t-statistic and p-value
for t_val in [1.0, 1.96, 2.5, 3.0, 4.0]:
# degrees of freedom = large sample -> t ~ normal
p = 2 * stats.t.sf(abs(t_val), df=100) # two-tailed
print(f't = {t_val:4.2f} -> p = {p:.4f} '
f'({'significant' if p < 0.05 else 'not significant'})')Confidence Intervals for the Mean Difference
A p-value alone does not tell you the magnitude of the effect. Always compute a confidence interval for the mean difference. A 95% CI that includes zero is consistent with p > 0.05 (not significant); one that excludes zero means the difference is significant. The CI also tells you whether the effect size is practically meaningful — a statistically significant difference of $0.01 in revenue may be irrelevant, while a $50 difference with p=0.06 may still matter for the business.
import numpy as np
from scipy import stats
np.random.seed(0)
control = np.random.normal(25, 8, 80)
variant = np.random.normal(28, 8, 80)
diff = variant.mean() - control.mean()
se = np.sqrt(control.var()/len(control) + variant.var()/len(variant))
df = len(control) + len(variant) - 2
t_crit = stats.t.ppf(0.975, df=df)
ci_low = diff - t_crit * se
ci_high = diff + t_crit * se
print(f'Mean difference: {diff:.2f}')
print(f'95% CI: [{ci_low:.2f}, {ci_high:.2f}]')
print('CI excludes zero:', ci_low > 0 or ci_high < 0)Effect Size: Cohen's d
Statistical significance depends on sample size — with large enough samples, even trivial differences become significant. Cohen's d measures practical significance (effect size): the mean difference divided by the pooled standard deviation. Guidelines: d < 0.2 is negligible, 0.2–0.5 is small, 0.5–0.8 is medium, > 0.8 is large. Always report effect size alongside p-values — a significant p-value with d = 0.05 means the difference is real but probably not meaningful in practice.
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(25, 8, 200)
g2 = np.random.normal(28, 8, 200)
stat, p = stats.ttest_ind(g1, g2)
# Cohen's d
pooled_std = np.sqrt((g1.var() + g2.var()) / 2)
cohens_d = (g2.mean() - g1.mean()) / pooled_std
print(f'p-value: {p:.4f}')
print(f'Cohen\'s d: {cohens_d:.3f}')
if cohens_d < 0.2: print('Effect: negligible')
elif cohens_d < 0.5: print('Effect: small')
elif cohens_d < 0.8: print('Effect: medium')
else: print('Effect: large')Assumptions of the T-Test
The independent t-test assumes: (1) Independence — observations within each group are independent of each other; (2) Normality — data in each group is approximately normal (robust for n > 30 via CLT); (3) for Student's t-test (equal_var=True), equal variances. Welch's t-test (equal_var=False) relaxes assumption 3 and is preferred. When normality is seriously violated with small samples (< 30), use the Mann-Whitney U test instead.
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(10, 2, 30)
g2 = np.random.normal(11, 5, 30) # Very different variance!
# Levene test for equal variances
stat_l, p_l = stats.levene(g1, g2)
print(f'Levene test p: {p_l:.4f}')
if p_l < 0.05:
print('Unequal variances -> use Welch\'s (equal_var=False)')
stat, p = stats.ttest_ind(g1, g2, equal_var=False)
else:
print('Equal variances OK -> Student\'s t-test')
stat, p = stats.ttest_ind(g1, g2, equal_var=True)
print(f'Result: t={stat:.3f}, p={p:.4f}')T-Tests on Pandas Series
In practice, the data you want to test lives in a Pandas DataFrame column. You can pass a Pandas Series directly to scipy.stats functions — they work seamlessly with Series as well as NumPy arrays. A common workflow: filter the DataFrame to get each group's Series, run the t-test, and store results in a summary DataFrame. This pattern scales to testing many pairs of columns or groups in a loop.
import pandas as pd
import numpy as np
from scipy import stats
np.random.seed(0)
df = pd.DataFrame({
'group': ['A']*60 + ['B']*60,
'revenue': np.concatenate([
np.random.normal(100, 20, 60),
np.random.normal(110, 22, 60)
])
})
grp_a = df.loc[df['group'] == 'A', 'revenue']
grp_b = df.loc[df['group'] == 'B', 'revenue']
stat, p = stats.ttest_ind(grp_a, grp_b, equal_var=False)
print(f'A mean: {grp_a.mean():.2f}, B mean: {grp_b.mean():.2f}')
print(f'p-value: {p:.4f}')Multiple Comparisons Problem
Running many t-tests simultaneously inflates the chance of a false positive. If you run 20 t-tests at α=0.05, you expect 1 false positive by chance. This is the multiple comparisons problem. Apply the Bonferroni correction: divide α by the number of tests (p_threshold = 0.05 / n_tests). For more power with less conservatism, use the Benjamini-Hochberg False Discovery Rate (FDR) correction available in statsmodels. Always correct for multiple comparisons in A/B testing with many metrics.
import numpy as np
from scipy import stats
np.random.seed(0)
n_tests = 10
results = []
for i in range(n_tests):
g1 = np.random.normal(0, 1, 50)
g2 = np.random.normal(0.1, 1, 50) # Tiny true effect
_, p = stats.ttest_ind(g1, g2)
results.append(p)
print('p-values:', [round(p, 3) for p in results])
bonferroni_thresh = 0.05 / n_tests
print(f'Bonferroni threshold: {bonferroni_thresh}')
print('Significant after Bonferroni:', sum(p < bonferroni_thresh for p in results))Quick Check
Test your understanding of Data Analysis concepts from this lesson.
Lesson Recap
In this lesson you learned: ttest_1samp tests a sample mean against a reference value, ttest_ind (Welch's with equal_var=False) compares two independent groups, and ttest_rel handles paired measurements. Always report Cohen's d alongside the p-value to distinguish statistical from practical significance. Next up we test relationships between categorical variables with the chi-squared test.
Questions Fréquemment Posées
La leçon « Tests t pour comparer des moyennes » est-elle gratuite ?
Oui — le texte complet de « Tests t pour comparer des moyennes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Pandas & NumPy Academy, passe à CoddyKit PRO. Le cours Pandas & NumPy Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Tests t pour comparer des moyennes » ?
Effectuez des tests t à un échantillon, à deux échantillons indépendants et appariés avec scipy.stats, puis interprétez les intervalles de confiance. Tu pratiques Pandas & NumPy Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Pandas & NumPy Academy ?
Aucune expérience préalable n'est requise. Pandas & NumPy Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Tests t pour comparer des moyennes » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Pandas & NumPy Academy ?
Oui. Chaque leçon Pandas & NumPy Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Statistiques descriptives et tests de normalité
- Tests t pour comparer des moyennes
- Test du khi carré d’indépendance
- ANOVA et tests post-hoc