Abbiamo avuto modo di vedere, nel post sul test delle ipotesi, come verificare se la media di un campione sia compatibile con una certa ipotesi sulla popolazione. Ma nella pratica il caso più comune è confrontare due gruppi.
Un farmaco abbassa davvero la pressione più del placebo? Un corso di formazione migliora i punteggi? Una nuova landing page produce un CTR più alto? In tutti questi casi abbiamo due gruppi (trattamento vs controllo, prima vs dopo, variante A vs B) e vogliamo capire se le medie sono diverse. Lo strumento giusto è il t-test per due campioni.
Per orientarci subito:
| Situazione | Test |
|---|---|
| Due gruppi diversi (es. uomini vs donne) | t-test per campioni indipendenti |
| Prima e dopo sullo stesso soggetto | t-test appaiato (paired) |
| Due varianti di pagina web (A/B test) | t-test per campioni indipendenti |
| Pressione prima e dopo una terapia | t-test appaiato |
La scelta tra i due test non è tecnica: è concettuale. Se i dati sono appaiati e usiamo un test indipendente, perdiamo potenza perché buttiamo via l’informazione sull’accoppiamento. Se usiamo un test appaiato su dati indipendenti, violiamo l’assunzione di indipendenza e rischiamo di trovare significatività dove non c’è.
Quando usare il t-test per campioni indipendenti?
Condizioni di validità
Perché il test sia valido, servono alcune condizioni:
- Un campione casuale per ciascuna popolazione
- Le osservazioni all’interno di ciascun campione sono indipendenti
- I due campioni sono indipendenti tra loro
- Le osservazioni provengono da popolazioni approssimativamente normali, oppure la numerosità campionaria è sufficientemente grande
Il t-test è piuttosto robusto a moderate deviazioni dalla normalità, soprattutto quando il campione è numeroso (n ≥ 30 per gruppo). Diventa invece problematico con campioni molto piccoli e distribuzioni fortemente asimmetriche.
Ipotesi:
\( H_0 : \mu_1 = \mu_2 \\ \) \( H_a : \mu_1 \neq \mu_2 \\ \)In altri termini: $\( H_0 : \mu_1 – \mu_2 = 0 \)\( , \)\( H_a : \mu_1 – \mu_2 \neq 0 \)$
La statistica test
Tutto parte dalla differenza tra le medie osservate. Calcoliamo il valore di t:
\( t = \frac{(\bar{x}_1 – \bar{x}_2) – (\mu_1 – \mu_2)}{SE_{(\bar{x}_1 – \bar{x}_2)}} \\ \)Dove:
- $\( \bar{x}_1 – \bar{x}_2 \)$ è la differenza osservata tra le medie campionarie
- $\( \mu_1 – \mu_2 \)$ è la differenza ipotizzata sotto H₀ (zero)
- $\( SE_{(\bar{x}_1 – \bar{x}_2)} \)$ è l’errore standard della differenza
L’errore standard si calcola così — e qui arriva il primo punto importante:
\( SE_{(\bar{x}_1 – \bar{x}_2)} = \sqrt{\frac{s^2_1}{n_1} + \frac{s^2_2}{n_2}} \\ \)N.B.: questa è la formula di Welch — non assume varianze uguali tra i due gruppi, ed è più robusta quando i campioni hanno numerosità o variabilità diverse. Per impostazione predefinita, t.test() in R usa il test di Welch, non il t-test classico di Student. È la scelta più prudente nella pratica: se non c’è un motivo forte per assumere varianze uguali, Welch è preferibile.
Se invece sappiamo per certo che le varianze sono simili (campioni bilanciati con varianze vicine), possiamo usare l’argomento var.equal = TRUE, che corrisponde al t-test classico con varianza pooled (“varianze unite”). Per un confronto più sistematico tra i due approcci, rimando alla Guida ai Test Statistici.
I gradi di libertà? Li lascio calcolare a R (usa l’approssimazione di Welch-Satterthwaite, un po’ complessa a mano). In alternativa, approccio conservativo: df = min(n₁, n₂) − 1.
Verifica delle assunzioni in R
Prima di eseguire il test, verifichiamo la normalità:
# Test di Shapiro-Wilk per ciascun gruppo
shapiro.test(varA)
shapiro.test(varB)
# Q-Q plot per ispezione visiva
par(mfrow = c(1, 2))
qqnorm(varA, main = "Gruppo A")
qqline(varA)
qqnorm(varB, main = "Gruppo B")
qqline(varB)Se il p-value dello Shapiro-Wilk è maggiore di 0,05, non abbiamo evidenze sufficienti per rifiutare l’ipotesi di normalità.
Un esempio con dati reali
Facciamo un esempio al volo. Supponiamo di avere due varianti di landing page per una campagna SEO: la versione A (quella attuale, il controllo) e la versione B (con un nuovo titolo e CTA). Vogliamo sapere se la nuova versione produce un CTR medio più alto. Prendiamo 10 giorni di traffico per ciascuna variante e misuriamo il CTR percentuale:
varA <- c(2.8, 3.1, 3.5, 2.9, 3.3, 3.0, 2.7, 3.2, 3.4, 3.1)
varB <- c(3.2, 3.8, 3.5, 4.1, 3.6, 3.9, 3.3, 3.7, 4.0, 3.4)
t.test(varA, varB) Welch Two Sample t-test
data: varA and varB
t = -3.092, df = 17.6, p-value = 0.006297
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-0.831 -0.157
sample estimates:
mean of x mean of y
3.10 3.65
Interpretiamo l’output. La differenza media è di 0,55 punti percentuali (3,65 − 3,10), con un p-value di 0,0063 — ben sotto la soglia di 0,05. L’intervallo di confidenza al 95% va da −0,83 a −0,16: non contiene zero. Abbiamo evidenza statistica sufficiente per rifiutare H₀ a favore dell’ipotesi alternativa: il CTR medio della variante B è diverso da quello della variante A.
Attenzione: il p-value ci dice se c’è una differenza. Non ci dice quanto è grande. Con campioni grandi, qualsiasi differenza — anche trascurabile — diventa “significativa”. Per questo serve una misura della dimensione dell’effetto.
Effect size: Cohen’s d
Il Cohen’s d standardizza la differenza dividendo per la deviazione standard pooled:
\( d = \frac{\bar{x}_1 – \bar{x}_2}{s_{pooled}} \\ \) \( s_{pooled} = \sqrt{\frac{(n_1 – 1)s^2_1 + (n_2 – 1)s^2_2}{n_1 + n_2 – 2}} \\ \)Calcoliamo in R:
n1 <- length(varA); n2 <- length(varB)
pooled_sd <- sqrt(((n1-1)*sd(varA)^2 + (n2-1)*sd(varB)^2) / (n1+n2-2))
d <- (mean(varB) - mean(varA)) / pooled_sd
d[1] 1.38Regola pratica: d ≈ 0,2 è piccolo, 0,5 medio, 0,8 grande. Il nostro d = 1,38 è un effetto grande — la differenza non è solo statisticamente significativa, è anche sostanziale.
Potenza del test
Se non troviamo una differenza significativa, è perché non c’è o perché il campione era troppo piccolo? La potenza (1 − β) è la probabilità di rilevare un effetto di data grandezza, se esiste.
Calcoliamo in R la numerosità necessaria per rilevare un effetto grande con l’80% di potenza:
library(pwr)
pwr.t.test(d = 0.8, power = 0.80, sig.level = 0.05,
type = "two.sample", alternative = "two.sided") Two-sample t test power calculation
n = 25.52
d = 0.8
sig.level = 0.05
power = 0.8
alternative = two.sidedServono circa 26 osservazioni per gruppo per avere l’80% di probabilità di rilevare un effetto grande. Con le nostre 10 osservazioni per gruppo, la potenza è molto più bassa — il fatto di aver trovato comunque significatività è un segnale che l’effetto è davvero marcato.
Quando usare il t-test per campioni dipendenti (appaiati)?
Quando gli stessi soggetti vengono misurati prima e dopo un intervento, abbiamo dati appaiati (paired data). Il test non confronta le medie dei due gruppi, ma la media delle differenze tra prima e dopo.
Condizioni di validità
- Il campione delle differenze è casuale
- Le differenze sono indipendenti tra loro
- Le differenze provengono da una popolazione approssimativamente normale (o n sufficientemente grande)
Ipotesi:
\( H_0 : \delta = 0 \\ \) \( H_a : \delta \neq 0 \\ \)dove δ è la media delle differenze nella popolazione.
La formula è analoga a quella del test a un campione, applicata alle differenze:
\( t = \frac{\bar{d} – \delta}{SE_{\bar{d}}} \\ \)dove $\( \bar{d} \)\( è la media delle differenze campionarie e \)\( SE_{\bar{d}} = \frac{s_d}{\sqrt{n}} \)$ è l’errore standard.
La deviazione standard delle differenze:
\( s_d = \sqrt{\frac{\Sigma(d – \bar{d})^2}{n – 1}} \\ \)Verifica delle assunzioni in R
diff <- dopo - prima
shapiro.test(diff)
# Ispezione visiva
qqnorm(diff)
qqline(diff)Un esempio con dati reali
Immaginiamo questo scenario: un docente di SEO vuole valutare l’efficacia del suo corso intensivo. Somministra un test di 100 punti ai partecipanti il primo giorno (pre) e lo stesso test alla fine del corso (post). Gli stessi studenti — non due gruppi diversi — vengono misurati due volte. Ecco i punteggi:
pre <- c(68, 75, 82, 71, 79, 65, 73, 77, 70, 74)
post <- c(72, 78, 85, 76, 82, 70, 75, 80, 74, 79)
diff <- post - pre
diff[1] 4 3 3 5 3 5 2 3 4 5
Verifichiamo la normalità delle differenze:
shapiro.test(diff) Shapiro-Wilk normality test
data: diff
W = 0.905, p-value = 0.248p > 0,05 → non rifiutiamo l’ipotesi di normalità. Procediamo:
t.test(pre, post, paired = TRUE) Paired t-test
data: pre and post
t = -7.746, df = 9, p-value = 2.86e-05
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
-4.171 -2.029
sample estimates:
mean difference
-3.1La differenza media è di 3,1 punti in positivo, con p < 0,001. L’intervallo di confidenza al 95% va da −4,17 a −2,03 punti: non contiene zero. Esiste evidenza statistica a favore di un miglioramento significativo dopo il corso.
Effect size per dati appaiati
d_paired <- mean(diff) / sd(diff)
d_paired[1] 2.45Attenzione: il Cohen’s d per dati appaiati tende a essere molto più grande rispetto al caso indipendente, perché la variabilità tra soggetti viene rimossa dal confronto entro-soggetti. È fisiologico, non un errore.
Diagramma decisionale

Una versione testuale del ragionamento:
- Stessi soggetti misurati due volte? → t-test appaiato
- Due gruppi indipendenti? → t-test di Welch (default)
- Dati non normali e campione piccolo? → test non parametrico (Mann-Whitney o Wilcoxon)
Quando NON usare il t-test
Il t-test è uno strumento potente, ma non universale:
- Distribuzioni fortemente asimmetriche con campioni piccoli (n < 15 per gruppo): il t-test perde affidabilità. Meglio il test di Mann-Whitney (wilcox.test in R) per campioni indipendenti, o il test di Wilcoxon signed-rank per dati appaiati.
- Più di due gruppi: serve l’analisi della varianza (ANOVA), di cui parleremo in un prossimo articolo.
- Dati ordinali: il t-test lavora su medie, che presuppongono dati almeno su scala a intervalli. Per ranking o scale Likert, meglio i test non parametrici.
FAQ
Qual è la differenza tra t-test appaiato e indipendente?
Nel t-test appaiato confrontiamo la media delle differenze entro ciascun soggetto (prima/dopo). In quello indipendente confrontiamo le medie di due gruppi separati. La scelta dipende dal disegno sperimentale, non dalla nostra preferenza.
Quando usare Welch invece del t-test classico?
Sempre, per default. Welch non assume varianze uguali ed è più robusto. Usa var.equal = TRUE solo se hai un motivo solido per credere che le varianze siano simili (campioni bilanciati con varianze vicine).
Il t-test funziona con campioni piccoli?
Sì, purché i dati siano approssimativamente normali. Con n < 15 per gruppo, verifica sempre la normalità con shapiro.test().
Cosa fare se i dati non sono normali?
Usa wilcox.test() in R: per campioni indipendenti (Mann-Whitney) o con paired = TRUE per dati appaiati (Wilcoxon signed-rank).
Prova tu
Prendi i dati dell’esempio indipendente e calcola:
- Il test a una coda: la variante B ha un CTR maggiore della A? (alternative = “greater”)
- Quale numerosità servirebbe per rilevare un effetto medio (d = 0,5) con potenza 0,80?
Abbiamo visto due strumenti fondamentali per confrontare gruppi: il t-test per campioni indipendenti, cavallo di battaglia degli A/B test, e il t-test appaiato, insostituibile nei disegni pre/post. In entrambi i casi il p-value da solo non basta: effect size, potenza e intervalli di confidenza completano il quadro. Nel prossimo articolo affronteremo il caso di tre o più gruppi — e lì entrerà in scena l’analisi della varianza (ANOVA).
Per approfondire
Per tutti i dettagli formali sul confronto tra campioni — pooled vs Welch, campioni appaiati, verifica delle assunzioni — Statistica di Newbold, Carlson e Thorne resta il riferimento più completo in italiano. Amazon
Ciao, bell’articolo!
Quando calcoli l’errore standard delle medie del campione
quelle varianze sotto la radice, ovvero s^2_1 e s^2_2, sono varianza campionarie già corrette, oppure sono le varianze semplici?
Grazie