5 Test t di Student per campioni indipendenti
- eseguire un test t di Student per il confronto tra due gruppi indipendenti;
- interpretare correttamente i risultati integrando valore-p, intervalli di confidenza e dimensione dell’effetto;
- comprendere i limiti concettuali e operativi del test e le principali alternative metodologiche.
- Comprendere la logica generale del test di ipotesi frequentista.
- Avere familiarità con la distinzione tra significatività statistica ed entità dell’effetto.
- Lettura consigliata: Bayesian estimation supersedes the t test (Kruschke, 2013).
5.1 Inquadramento epistemologico
Il test t per campioni indipendenti affronta una domanda inferenziale ricorrente nelle scienze empiriche:
le differenze osservate tra due gruppi riflettono una reale differenza tra le popolazioni, oppure possono essere spiegate come fluttuazioni casuali del campionamento?
Nel paradigma frequentista, questa domanda viene riformulata in termini controfattuali: si assume inizialmente che le popolazioni abbiano la stessa media (ipotesi nulla) e si valuta quanto i dati osservati sarebbero rari se tale assunzione fosse vera. Come per tutti i test di ipotesi frequentisti, l’obiettivo non è stimare la probabilità dell’ipotesi, ma controllare errori decisionali nel lungo periodo.
5.2 Assunzioni del test
Nel confronto tra due gruppi indipendenti, il test t di Student classico si basa su alcune assunzioni fondamentali:
Indipendenza delle osservazioni. Le osservazioni all’interno e tra i gruppi devono essere indipendenti. Questa è un’assunzione di disegno sperimentale, non verificabile a posteriori.
Normalità delle popolazioni. Ciascun gruppo dovrebbe provenire da una popolazione approssimabile con una distribuzione normale. In pratica, il test è relativamente robusto a violazioni moderate di questa assunzione, soprattutto per campioni di dimensione non troppo piccola.
Uguaglianza delle varianze (omoschedasticità). Le varianze delle due popolazioni dovrebbero essere uguali. Quando questa assunzione non è plausibile, si utilizza il test t di Welch, che corregge sia la statistica test sia i gradi di libertà.
Dal punto di vista epistemologico, è importante notare che queste assunzioni definiscono il modello probabilistico entro cui il valore-\(p\) è interpretabile.
5.3 Formulazione del test
5.3.1 Ipotesi
Nel caso più comune, l’ipotesi nulla afferma che le due popolazioni abbiano la stessa media:
\[ H_0: \mu_1 = \mu_2. \]
L’ipotesi alternativa considera la possibilità che le medie differiscano:
\[ H_1: \mu_1 \neq \mu_2, \] oppure, in versioni direzionali, che una media sia maggiore o minore dell’altra.
5.3.2 Statistica test
La statistica t confronta la differenza osservata tra le medie con la variabilità attesa sotto l’ipotesi nulla:
\[ t = \frac{\bar{X}_1 - \bar{X}_2}{s_p \sqrt{\frac{1}{n_1} + \frac{1}{n_2}}}, \] dove \(s_p\) è la deviazione standard pooled:
\[ s_p = \sqrt{\frac{(n_1 - 1)s_1^2 + (n_2 - 1)s_2^2}{n_1 + n_2 - 2}}. \]
Sotto l’ipotesi nulla, la statistica t segue una distribuzione t di Student con \(n_1 + n_2 - 2\) gradi di libertà.
Questa costruzione riflette una logica già vista nel test per una media: la differenza tra medie viene standardizzata rispetto alla sua incertezza campionaria.
5.4 Esempio pratico
Consideriamo un confronto tra il peso corporeo di un gruppo di donne e un gruppo di uomini:
peso_donne <- c(38.9, 61.2, 73.3, 21.8, 63.4, 64.6, 48.4, 48.8, 48.5)
peso_uomini <- c(67.8, 60, 63.4, 76, 89.4, 73.3, 67.3, 61.3, 62.4)
cat("Donne:\n")
#> Donne:
cat(" Media:", round(mean(peso_donne), 2), "kg\n")
#> Media: 52.1 kg
cat(" Dev. std:", round(sd(peso_donne), 2), "kg\n")
#> Dev. std: 15.6 kg
cat(" n:", length(peso_donne), "\n\n")
#> n: 9
cat("Uomini:\n")
#> Uomini:
cat(" Media:", round(mean(peso_uomini), 2), "kg\n")
#> Media: 69 kg
cat(" Dev. std:", round(sd(peso_uomini), 2), "kg\n")
#> Dev. std: 9.38 kg
cat(" n:", length(peso_uomini), "\n")
#> n: 95.4.1 Calcolo manuale
n1 <- length(peso_donne)
n2 <- length(peso_uomini)
s_pool <- sqrt(((n1 - 1) * var(peso_donne) + (n2 - 1) * var(peso_uomini)) /
(n1 + n2 - 2))
t_stat <- (mean(peso_donne) - mean(peso_uomini)) /
(s_pool * sqrt(1/n1 + 1/n2))
df <- n1 + n2 - 2
p_value <- 2 * pt(abs(t_stat), df = df, lower.tail = FALSE)
cat("Deviazione standard pooled:", round(s_pool, 2), "\n")
#> Deviazione standard pooled: 12.9
cat("Statistica t:", round(t_stat, 3), "\n")
#> Statistica t: -2.78
cat("Gradi di libertà:", df, "\n")
#> Gradi di libertà: 16
cat("P-value:", round(p_value, 4), "\n")
#> P-value: 0.0133Il valore-p quantifica quanto una differenza almeno così grande sarebbe rara assumendo che le due popolazioni abbiano la stessa media.
5.4.2 Utilizzo di t.test()
t.test(peso_donne, peso_uomini, var.equal = TRUE)
#>
#> Two Sample t-test
#>
#> data: peso_donne and peso_uomini
#> t = -3, df = 16, p-value = 0.01
#> alternative hypothesis: true difference in means is not equal to 0
#> 95 percent confidence interval:
#> -29.75 -4.03
#> sample estimates:
#> mean of x mean of y
#> 52.1 69.05.4.3 Test di Welch
Il test t di Welch rappresenta una generalizzazione più robusta del test classico. Non assume uguaglianza delle varianze e utilizza:
- varianze separate per ciascun gruppo;
- gradi di libertà adattivi.
In R è l’opzione predefinita:
t.test(peso_donne, peso_uomini, var.equal = FALSE)
#>
#> Welch Two Sample t-test
#>
#> data: peso_donne and peso_uomini
#> t = -3, df = 13, p-value = 0.02
#> alternative hypothesis: true difference in means is not equal to 0
#> 95 percent confidence interval:
#> -30.0 -3.8
#> sample estimates:
#> mean of x mean of y
#> 52.1 69.0Dal punto di vista metodologico, il test di Welch è spesso preferibile, poiché riduce il rischio di errori quando le assunzioni di omoschedasticità sono violate.
5.5 Interpretazione dei risultati
Il valore-p suggerisce che la differenza osservata sarebbe poco compatibile con l’ipotesi di uguaglianza delle medie. Tuttavia, la significatività statistica da sola è insufficiente per una valutazione scientificamente completa.
5.5.1 Dimensione dell’effetto: \(d\) di Cohen
La dimensione dell’effetto quantifica la differenza in unità di deviazione standard:
\[ d = \frac{\bar{X}_1 - \bar{X}_2}{s_p}. \]
Un valore pari a 1.31 indica una differenza molto ampia sul piano pratico.
5.5.2 Intervallo di confidenza per la differenza
test_result <- t.test(peso_donne, peso_uomini, var.equal = TRUE)
cat("Differenza delle medie:", round(test_result$estimate[1] - test_result$estimate[2], 2), "kg\n")
#> Differenza delle medie: -16.9 kg
cat("IC al 95%: [", round(test_result$conf.int[1], 2), ", ",
round(test_result$conf.int[2], 2), "] kg\n")
#> IC al 95%: [ -29.8 , -4.03 ] kgL’intervallo di confidenza fornisce una stima della precisione e consente di valutare la plausibilità di diverse grandezze dell’effetto.
5.6 Come riportare i risultati
5.6.1 Versione sconsigliata
Una formulazione che si limiti a riportare la sola significatività statistica fornisce un resoconto incompleto:
“I risultati mostrano una differenza significativa tra i pesi medi delle donne e degli uomini (\(t\)(16) = −2.78, \(p\) = 0.01).”
5.6.2 Versione consigliata
Una comunicazione completa è più trasparente e più informativa:
“Il peso medio delle donne (\(M\) = 52.1 kg, \(DS\) = 15.6) è inferiore a quello degli uomini (\(M\) = 69.0 kg, \(DS\) = 9.0) di 16.9 kg (\(IC\) 95%: [4.0, 29.8]). La differenza è associata a una dimensione dell’effetto molto ampia (\(d\) = 1.31).”
Questa formulazione integra stima, incertezza e rilevanza pratica.
5.7 Limiti del test \(t\)
Il test t condivide i limiti strutturali dei test di ipotesi frequentisti:
- decisione dicotomica basata su soglie convenzionali;
- dipendenza dalla dimensione campionaria;
- incapacità di quantificare l’evidenza a favore dell’ipotesi nulla;
- interpretazione spesso ambigua del valore-p.
5.8 L’alternativa bayesiana
L’approccio bayesiano, come discusso da Kruschke (2013), rappresenta una valida alternativa. Fornisce distribuzioni posteriori complete, consente di esprimere direttamente le probabilità delle ipotesi, integra le informazioni pregresse, gestisce gli outlier con modelli più flessibili e separa chiaramente assenza di evidenza ed evidenza di assenza.
Riflessioni conclusive
Il test t di Student per campioni indipendenti rappresenta uno strumento centrale dell’inferenza frequentista per il confronto tra medie. Il suo uso risulta metodologicamente più solido quando l’interpretazione non si limita alla significatività statistica, ma integra stime puntuali, intervalli di confidenza e dimensioni dell’effetto.
La rigidità decisionale e le ambiguità interpretative del valore-\(p\) rendono tuttavia evidente la necessità di affiancare a questa procedura strumenti inferenziali più informativi. In questo senso, l’approccio bayesiano non va inteso come semplice alternativa tecnica, ma come paradigma epistemologico distinto, che affronta in modo più diretto le domande scientifiche sulla plausibilità delle ipotesi e sull’incertezza dei parametri.
sessionInfo()
#> R version 4.5.2 (2025-10-31)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Tahoe 26.2
#>
#> Matrix products: default
#> BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] C.UTF-8/UTF-8/C.UTF-8/C/C.UTF-8/C.UTF-8
#>
#> time zone: Europe/Rome
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] ragg_1.5.0 tinytable_0.15.2 withr_3.0.2
#> [4] systemfonts_1.3.1 patchwork_1.3.2 ggdist_3.3.3
#> [7] tidybayes_3.0.7 bayesplot_1.15.0 ggplot2_4.0.1
#> [10] reliabilitydiag_0.2.1 priorsense_1.2.0 posterior_1.6.1
#> [13] loo_2.9.0 rstan_2.32.7 StanHeaders_2.32.10
#> [16] brms_2.23.0 Rcpp_1.1.0 sessioninfo_1.2.3
#> [19] conflicted_1.2.0 janitor_2.2.1 matrixStats_1.5.0
#> [22] modelr_0.1.11 tibble_3.3.0 dplyr_1.1.4
#> [25] tidyr_1.3.2 rio_1.2.4 here_1.0.2
#>
#> loaded via a namespace (and not attached):
#> [1] svUnit_1.0.8 tidyselect_1.2.1 farver_2.1.2
#> [4] S7_0.2.1 fastmap_1.2.0 TH.data_1.1-5
#> [7] tensorA_0.36.2.1 digest_0.6.39 timechange_0.3.0
#> [10] estimability_1.5.1 lifecycle_1.0.5 survival_3.8-3
#> [13] magrittr_2.0.4 compiler_4.5.2 rlang_1.1.7
#> [16] tools_4.5.2 knitr_1.51 bridgesampling_1.2-1
#> [19] htmlwidgets_1.6.4 curl_7.0.0 pkgbuild_1.4.8
#> [22] RColorBrewer_1.1-3 abind_1.4-8 multcomp_1.4-29
#> [25] purrr_1.2.1 grid_4.5.2 stats4_4.5.2
#> [28] colorspace_2.1-2 xtable_1.8-4 inline_0.3.21
#> [31] emmeans_2.0.1 scales_1.4.0 MASS_7.3-65
#> [34] cli_3.6.5 mvtnorm_1.3-3 rmarkdown_2.30
#> [37] generics_0.1.4 otel_0.2.0 RcppParallel_5.1.11-1
#> [40] cachem_1.1.0 stringr_1.6.0 splines_4.5.2
#> [43] parallel_4.5.2 vctrs_0.6.5 V8_8.0.1
#> [46] Matrix_1.7-4 sandwich_3.1-1 jsonlite_2.0.0
#> [49] arrayhelpers_1.1-0 glue_1.8.0 codetools_0.2-20
#> [52] distributional_0.5.0 lubridate_1.9.4 stringi_1.8.7
#> [55] gtable_0.3.6 QuickJSR_1.8.1 pillar_1.11.1
#> [58] htmltools_0.5.9 Brobdingnag_1.2-9 R6_2.6.1
#> [61] textshaping_1.0.4 rprojroot_2.1.1 evaluate_1.0.5
#> [64] lattice_0.22-7 backports_1.5.0 memoise_2.0.1
#> [67] broom_1.0.11 snakecase_0.11.1 rstantools_2.5.0
#> [70] gridExtra_2.3 coda_0.19-4.1 nlme_3.1-168
#> [73] checkmate_2.3.3 xfun_0.55 zoo_1.8-15
#> [76] pkgconfig_2.0.3