Pandas & NumPy Academy · Les

T-toetsen voor het vergelijken van gemiddelden

Voer een t-toets voor één steekproef, een onafhankelijke t-toets voor twee steekproeven en een gepaarde t-toets uit met scipy.stats en interpreteer betrouwbaarheidsintervallen.

Les 2 van 413 stappen

T-toetsen voor het vergelijken van gemiddelden is een gratis Pandas & NumPy Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Pandas & NumPy Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Wat is een t-toets?

Een t-toets is een hypothesetoets die bepaalt of een verschil tussen groepsgemiddelden statistisch significant is of waarschijnlijk door toeval is ontstaan. De toets vergelijkt het waargenomen verschil met de variabiliteit in de gegevens en produceert een t-statistiek en een p-waarde. Als p ≤ 0.05 (de gebruikelijke drempelwaarde), verwerpen we de nulhypothese dat de gemiddelden gelijk zijn. Er zijn drie veelvoorkomende typen: de t-toets voor één steekproef, de onafhankelijke t-toets voor twee steekproeven en de gepaarde t-toets, elk voor een ander experimenteel ontwerp.

T-toets voor één steekproef

De t-toets voor één steekproef toetst of het gemiddelde van een steekproef significant verschilt van een bekend of verondersteld populatiegemiddelde. Bijvoorbeeld: 'Verschilt onze gemiddelde bezorgtijd significant van de industrienorm van 3 dagen?' Gebruik scipy.stats.ttest_1samp(data, popmean). De nulhypothese is H₀: mean = popmean. Een kleine p-waarde leidt ertoe dat je H₀ verwerpt en concludeert dat het steekproefgemiddelde afwijkt van de doelwaarde.

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')

Onafhankelijke t-toets voor twee steekproeven

De t-toets voor twee onafhankelijke steekproeven vergelijkt de gemiddelden van twee onafhankelijke groepen. Bijvoorbeeld: ‘Levert de variant van de A/B-test gemiddeld meer omzet op dan de controlevariant?’ Gebruik scipy.stats.ttest_ind(group_a, group_b). De parameter equal_var is belangrijk: stel equal_var=False in (de t-toets van Welch) wanneer de twee groepen mogelijk verschillende varianties hebben. Dat is de veilige standaard voor de meeste echte gegevens.

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')

Eenzijdige versus tweezijdige toetsen

Standaard zijn t-toetsen tweezijdig: ze toetsen of gemiddelden in beide richtingen van elkaar verschillen (groter OF kleiner dan). Als je een gerichte hypothese hebt (‘de variant verhoogt de omzet’), gebruik je een eenzijdige toets met de parameter alternative: 'greater' of 'less'. Een eenzijdige toets heeft meer onderscheidend vermogen voor de specifieke richting, maar levert geen bewijs voor de andere richting. Bepaal de richting voordat je naar de gegevens kijkt om HARKing (Hypothesising After Results are Known) te voorkomen.

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}')

Gepaarde t-toets

De gepaarde t-toets gebruik je wanneer elke waarneming in groep A een natuurlijke partner heeft in groep B — bijvoorbeeld metingen vóór en na een behandeling bij dezelfde proefpersonen, of metingen in dezelfde winkels in twee verschillende maanden. Door te paren corrigeer je voor variatie tussen proefpersonen, waardoor de toets krachtiger wordt dan een t-toets voor onafhankelijke steekproeven met dezelfde gegevens. Gebruik scipy.stats.ttest_rel(before, after). De volgorde van de elementen moet overeenkomen: before[i] en after[i] moeten van dezelfde proefpersoon afkomstig zijn.

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')

De t-statistiek interpreteren

De t-statistiek geeft aan hoeveel standaardfouten het waargenomen verschil van nul afligt. Een t-statistiek van 2 betekent dat het waargenomen verschil 2 standaardfouten boven de waarde ligt die onder de nulhypothese wordt verwacht. Bij een tweezijdige toets met α=0,05 en een grote steekproef is de kritieke waarde ongeveer ±1,96 — dus geeft |t| > 1,96 p < 0,05. De p-waarde zet de t-statistiek om in een kans, zodat je de uitkomst gemakkelijker kunt interpreteren zonder tabellen van de t-verdeling te raadplegen.

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'})')

Betrouwbaarheidsintervallen voor het gemiddelde verschil

Een p-waarde vertelt je op zichzelf niet hoe groot het effect is. Bereken altijd een betrouwbaarheidsinterval voor het gemiddelde verschil. Een 95%-BI dat nul bevat, komt overeen met p > 0,05 (niet significant); als het nul niet bevat, is het verschil significant. Het BI laat ook zien of de effectgrootte praktisch betekenisvol is — een statistisch significant omzetverschil van $0,01 kan irrelevant zijn, terwijl een verschil van $50 met p=0,06 toch belangrijk kan zijn voor het bedrijf.

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)

Effectgrootte: Cohen's d

Statistische significantie hangt af van de steekproefgrootte — bij voldoende grote steekproeven worden zelfs verwaarloosbare verschillen significant. Cohen's d meet de praktische significantie (effectgrootte): het gemiddelde verschil gedeeld door de gepoolde standaardafwijking. Richtlijnen: d < 0,2 is verwaarloosbaar, 0,2–0,5 is klein, 0,5–0,8 is middelgroot en > 0,8 is groot. Rapporteer de effectgrootte altijd naast de p-waarden — een significante p-waarde met d = 0,05 betekent dat het verschil echt is, maar in de praktijk waarschijnlijk niet betekenisvol.

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')

Aannames van de t-toets

De t-toets voor onafhankelijke steekproeven gaat uit van: (1) onafhankelijkheid — waarnemingen binnen elke groep zijn onafhankelijk van elkaar; (2) normaliteit — de gegevens in elke groep zijn ongeveer normaal verdeeld (robuust voor n > 30 dankzij de centrale limietstelling); (3) voor de t-toets van Student (equal_var=True): gelijke varianties. De t-toets van Welch (equal_var=False) laat aanname 3 los en heeft de voorkeur. Wanneer de normaliteit bij kleine steekproeven (< 30) ernstig wordt geschonden, gebruik je in plaats daarvan de Mann-Whitney-U-toets.

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-toetsen op Pandas Series

In de praktijk staan de gegevens die je wilt toetsen in een kolom van een Pandas DataFrame. Je kunt een Pandas Series rechtstreeks doorgeven aan functies van scipy.stats — die werken probleemloos met zowel Series als NumPy-arrays. Een veelgebruikte werkwijze is: filter het DataFrame om de Series van elke groep te verkrijgen, voer de t-toets uit en sla de resultaten op in een samenvattend DataFrame. Dit patroon is geschikt voor het toetsen van veel paren kolommen of groepen in een lus.

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}')

Probleem van meerdere vergelijkingen

Veel t-toetsen tegelijk uitvoeren vergroot de kans op een vals-positief resultaat. Als je 20 t-toetsen uitvoert met α=0,05, verwacht je door toeval 1 vals-positief resultaat. Dit is het probleem van meerdere vergelijkingen. Pas de Bonferroni-correctie toe: deel α door het aantal toetsen (p_threshold = 0.05 / n_tests). Gebruik voor meer onderscheidend vermogen met minder behoudendheid de Benjamini-Hochberg-correctie voor het percentage valse ontdekkingen (FDR) uit statsmodels. Corrigeer bij A/B-tests met veel statistieken altijd voor meerdere vergelijkingen.

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))

Korte controle

Test je begrip van de concepten voor gegevensanalyse uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat ttest_1samp het gemiddelde van een steekproef toetst tegen een referentiewaarde, dat ttest_ind (de t-toets van Welch met equal_var=False) twee onafhankelijke groepen vergelijkt en dat ttest_rel gepaarde metingen verwerkt. Rapporteer altijd Cohen's d naast de p-waarde om statistische en praktische significantie van elkaar te onderscheiden. Hierna toetsen we verbanden tussen categorische variabelen met de chi-kwadraattoets.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “T-toetsen voor het vergelijken van gemiddelden” gratis?

Ja — de volledige tekst van “T-toetsen voor het vergelijken van gemiddelden” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Pandas & NumPy Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Wat leer ik in “T-toetsen voor het vergelijken van gemiddelden”?

Voer een t-toets voor één steekproef, een onafhankelijke t-toets voor twee steekproeven en een gepaarde t-toets uit met scipy.stats en interpreteer betrouwbaarheidsintervallen. Je oefent met Pandas & NumPy Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Pandas & NumPy Academy te beginnen?

Ervaring vooraf is niet nodig. Pandas & NumPy Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.

Hoe lang duurt de les “T-toetsen voor het vergelijken van gemiddelden”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Pandas & NumPy Academy?

Ja. Elke les over Pandas & NumPy Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Beschrijvende statistiek en normaliteitstoetsen
  2. T-toetsen voor het vergelijken van gemiddelden
  3. Chi-kwadraattoets voor onafhankelijkheid
  4. ANOVA en post-hoc-toetsen
← Terug naar Pandas & NumPy Academy