Test t in Python con SciPy: Guida Pratica a Student, Welch e p-value

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Test t vs Welch la guida pratica in Python

Tutti ci siamo passati. All’università, o studiando per conto tuo, concetti come p-value, test t e ANOVA sembrano filare lisci. La teoria ha senso. Poi ti siedi davanti allo schermo, importi SciPy, passi i tuoi array a una funzione e Python ti sputa fuori una tupla di decimali infiniti.

A quel punto ti fermi e pensi:

“Ok, ma in soldoni questo numero mi sta dicendo che la nuova landing page funziona o no?”.

La verità è che conoscere la teoria non basta se non sai come tradurla nel codice di tutti i giorni.

Questo tutorial nasce per chiudere esattamente questo divario. Non ci limiteremo a fare un copia-incolla delle documentazioni ufficiali; prenderemo un caso reale, scriveremo il codice necessario e, soprattutto, vedremo come interpretare i numeri per evitare figuracce quando devi presentare i risultati.

 

Pubblicità

Setup: cosa serve

Per iniziare, non hai bisogno di librerie complesse.

Useremo il pacchetto base della data science in Python, concentrandoci su SciPy, che rappresenta lo standard de facto per i test statistici:

import numpy as np
import pandas as pd
from scipy import stats

Facoltative ma utilissime:

import matplotlib.pyplot as plt
import seaborn as sns

👉 useremo principalmente SciPy, che è lo standard per i test statistici in Python.

Caso reale: dati di esempio

Un caso reale: A/B Testing sui dati

Immagina questo scenario: hai appena lanciato una nuova versione (Versione B) della tua landing page e vuoi confrontarla con la vecchia (Versione A). La domanda di business che ti pone il tuo team è diretta: “La nuova versione migliora davvero le conversioni o il tempo di permanenza?”

Per rispondere, simuliamo i dati di due campioni numerici:

import numpy as np
np.random.seed(42)
A = np.random.normal(loc=50, scale=10, size=100)
B = np.random.normal(loc=55, scale=10, size=100)

1. Test t (confronto tra medie)

Il test t per campioni indipendenti è lo strumento corretto quando hai una variabile numerica, vuoi confrontare due gruppi distinti e i dati presentano una distribuzione approssimativamente normale.

Proviamo a lanciare il test di base fornito da SciPy:

Test t indipendente

t_stat, p_value = stats.ttest_ind(A, B)
print(t_stat, p_value)
-4.7546959435052765 3.8191352626795345e-06

L’interpretazione rapida che tutti impariamo è quella di guardare il p-value: se è inferiore a 0.05, consideriamo la differenza statisticamente significativa. In questo caso, il valore è talmente vicino allo zero che non ci sono dubbi.

Tuttavia, fermarsi qui significa commettere un errore procedurale comune: stiamo dando per scontato che la varianza tra i due gruppi sia identica.

👉 Regola pratica:

if p_value < 0.05:
    print("Differenza significativa")
else:
    print("Nessuna evidenza di differenza")
Differenza significativa

La variante robusta: Il Test di Welch

Il test t classico (quello di Student) assume rigorosamente che i due gruppi abbiano la stessa varianza, ovvero la stessa “dispersione” dei dati.

Se questa ipotesi è falsa (e nel mondo reale lo è quasi sempre) il test può portarti a conclusioni sbagliate, sottostimando o sovrastimando la significatività della differenza.

Forse potrebbe interessarti anche:  Distribuzione Ipergeometrica: Guida Pratica con Esercizi Aziendali e Codice Python

Per tutelarsi, la scelta migliore è usare il Test di Welch, che indichiamo a Python aggiungendo semplicemente un parametro:

stats.ttest_ind(A, B, equal_var=False)

 Output: 
TtestResult(statistic=-4.754695943505277, pvalue=3.824684669406089e-06, df=197.52867431439725)

Cosa cambia con equal_var=False?

Scrivendo equal_var=False, diciamo all’algoritmo di non assumere che le varianze siano identiche.

Questo approccio adatta automaticamente i gradi di libertà ed è nettamente più affidabile nella pratica lavorativa, tanto da essere la scelta di default di molti data scientist esperti.

 In sintesi: Perché è importante?

Il test t classico (Student) assume:

  • stessa varianza nei due gruppi
  • stessa “dispersione” dei dati

👉 Se questa ipotesi è falsa, il test può:

  • sottostimare o sovrastimare la significatività
  • portarti a conclusioni sbagliate

 Il test di Welch ( quello che abbiamo usato)

È più robusto perché:

  • non richiede varianze uguali
  • adatta automaticamente i gradi di libertà
  • è più affidabile nella pratica reale

Analisi completa dell’output

Ora che abbiamo lanciato il test corretto, analizziamo i tre valori restituiti dalla funzione per capire esattamente cosa stiamo leggendo.

statistic (-4.75):

Rappresenta la distanza standardizzata tra le due medie.

A livello concettuale, si calcola come:

[math]\displaystyle \begin{aligned} t = \frac{\bar{x}_1 – \bar{x}_2}{\text{errore standard}} \end{aligned}[/math]

Un valore alto in valore assoluto indica una differenza marcata tra i gruppi. Il segno negativo ci informa semplicemente che la media del gruppo A è inferiore a quella del gruppo B.

p-value (3.82e-06):

È la probabilità di osservare una differenza così estrema qualora le due medie fossero, nella realtà, perfettamente uguali ([math]H_0[/math]). Essendo un numero infinitesimale, possiamo scartare con sicurezza l’ipotesi che la differenza sia frutto del caso. Attenzione: un [math]p\text{-value}[/math] basso certifica che la differenza esiste, non che sia “enorme”.

df (197.53):

I gradi di libertà. Nel test classico questo valore è sempre un numero intero calcolato come [math]n_1 + n_2 – 2[/math]. Nel test di Welch, invece, i gradi di libertà vengono stimati con una formula più complessa che penalizza il risultato in base alle differenze di varianza, portando a valori decimali. Un numero alto (vicino a 200) indica che il test gode di un’ottima stabilità.

Interpretazione completa

Mettiamo tutto insieme:

  • [math]t = -4.75[/math] → differenza forte
  • [math]p\text{-value} \approx 0[/math] → evidenza schiacciante
  • [math]df \approx 197[/math] → stima affidabile

Conclusione corretta

  • 👉 I due gruppi hanno medie significativamente diverse
  • 👉 La differenza NON è spiegabile con il caso
  • 👉 Il gruppo B performa meglio di A

⚠️ Il pezzo mancante: la Dimensione dell’Effetto (Cohen’s d)

Molte analisi si fermano al p-value, ma in contesti aziendali questo è un errore grave.

La significatività statistica non coincide con l’importanza pratica.

Se hai milioni di visite sulla tua landing page, anche un miglioramento dello 0.001% risulterà statisticamente significativo, ma probabilmente non giustificherà i costi di implementazione della nuova pagina. Per capire quanto conta davvero la differenza, ci serve una metrica di impatto: il d di Cohen.

Ecco come calcolarlo in Python, ricordandoci di utilizzare la varianza campionaria (ddof=1):

mean_diff = np.mean(A) - np.mean(B)
# Usiamo ddof=1 per ottenere la varianza campionaria
pooled_std = np.sqrt((np.var(A, ddof=1) + np.var(B, ddof=1)) / 2) 

cohen_d = mean_diff / pooled_std
print(cohen_d)
-0.67580305413896

Di default, NumPy calcola la varianza della popolazione (gradi di libertà = 0). Quando si lavora con campioni statistici per inferenza, si dovrebbe sempre usare la varianza campionaria, impostando il parametro ddof=1 (Delta Degrees of Freedom).

Come si interpreta il risultato?

Forse potrebbe interessarti anche:  Test Chi-Quadro: Guida Completa all'Adattamento e all'Indipendenza (con Esempi Pratici e Python)

Le linee guida standard suggeriscono che un valore assoluto di 0.2 rappresenta un effetto piccolo, 0.5 un effetto medio e 0.8 un effetto grande.

Nel nostro esempio, con un d pari a circa 0.67, non solo abbiamo la certezza statistica che i due gruppi si comportano in modo diverso, ma sappiamo anche che la Versione B della landing page genera un miglioramento di entità medio-grande nel mondo reale.

Abbiamo risposto alla domanda del team, con i numeri a supporto.

Quale test scegliere?

1. Il bivio della Normalità

La prima domanda è: i miei dati seguono una distribuzione normale (a campana)?

  • SÌ: Passa ai test Parametrici (Test t).
  • NO: Se i dati sono fortemente asimmetrici o il campione è molto piccolo ([math]n < 30[/math]), usa i test Non Parametrici (es. Mann-Whitney U-test).

2. Il bivio della Varianza (Omoschedasticità)

Se sei nel campo dei test parametrici, guarda la dispersione dei dati:

  • Varianze Uguali: Puoi usare il Test t di Student classico.
  • Varianze Diverse: Devi usare il Test di Welch (equal_var=False).

Consiglio pro: Se hai dubbi, scegli sempre Welch. È più sicuro.

3. Il bivio del numero di gruppi

  • 2 Gruppi: Test t o Mann-Whitney.
  • [math]3+[/math] Gruppi: ANOVA o Kruskal-Wallis (che vedremo nella Parte 2).

Tabella di Consultazione Rapida

Se i dati sono… E vuoi confrontare… Il test giusto è: Funzione Python (SciPy)
Normali 2 medie (varianze uguali) Test t di Student
stats.ttest_ind(A, B)
Normali 2 medie (varianze diverse) Test di Welch
stats.ttest_ind(A, B, equal_var=False)
Non Normali 2 distribuzioni (mediane) Mann-Whitney U
stats.mannwhitneyu(A, B)
Normali [math]3+[/math] medie ANOVA (One-way)
stats.f_oneway(A, B, C)
  • Visualizza: Crea un istogramma o un boxplot. Se vedi outlier giganti o distribuzioni “strane”, la normalità è a rischio.
  • Valida: Se vuoi essere matematicamente certo, lancia:
    Se il [math]p\text{-value}[/math] è basso, i dati non sono normali.
  • Scegli:
  • Tutto ok? [math]\rightarrow[/math]
  • Dati sporchi? [math]\rightarrow[/math]
  • Misura l’impatto: Non chiudere mai l’analisi senza il d di Cohen.

 I 4 Errori che “rompono” il tuo Test

1. La trappola della Normalità (Outliers)

Il Test t si basa sulla media. Se i tuoi dati contengono degli outliers (valori estremi dovuti a errori di tracciamento o bug), la media verrà trascinata verso l’alto o verso il basso, falsando la [math]t\text{-statistic}[/math].

Check: Hai visualizzato i dati con un boxplot o un istogramma?

Soluzione: Se i dati sono fortemente asimmetrici o pieni di outliers, il Test t non è adatto. Usa il Test di Mann-Whitney (U-test), che è l’equivalente non parametrico basato sui ranghi (posizioni) e non sulle medie.

2. Dimensione del campione e “p-hacking”

Se continui a monitorare il [math]p\text{-value}[/math] ogni ora mentre i dati arrivano e decidi di fermarti non appena vedi [math]p < 0.05[/math], stai barando (anche se non lo sai). Questo si chiama p-hacking.

Forse potrebbe interessarti anche:  Distribuzione ipergeometrica: teoria, esercizi svolti e applicazioni in Python

Check: Hai stabilito la dimensione del campione prima di iniziare il test?

Soluzione: Definisci la dimensione del campione necessaria tramite una Power Analysis. Una volta raggiunto quel numero, fermati e analizza i dati. Non prima.

3. Assunzioni sulla Varianza (Omoschedasticità)

Lo abbiamo visto con il Test di Welch: dare per scontato che i due gruppi oscillino allo stesso modo è un rischio inutile.

Check: I due gruppi hanno una varianza simile?

Soluzione: Se non vuoi rischiare, usa sempre equal_var=False. Non c’è quasi mai un reale svantaggio nell’usare Welch invece dello Student classico, ma c’è un enorme vantaggio in termini di robustezza.

4. L’errore di interpretazione: Significatività vs Realtà

Questo è l’errore “aziendale” più frequente. Un test può essere statisticamente significativo ma totalmente irrilevante a livello pratico.

Check: Hai calcolato il d di Cohen o un’altra misura di Effect Size?

Soluzione: Se il [math]p\text{-value}[/math] è [math]0.001[/math] ma il d di Cohen è [math]0.1[/math], hai trovato una differenza che esiste, ma è talmente piccola che probabilmente non sposterà di un millimetro il fatturato aziendale.


Esercizio di debug: Trova l’errore

Immagina di ricevere questo report da un collega:

“Ho analizzato il tempo di permanenza sul sito. Il gruppo A ha una media di 40s, il gruppo B di 42s. Il test t dice [math]p = 0.048[/math]. Abbiamo vinto, implementiamo la versione B!”

Perché dovresti essere scettico?

  • Marginalità: Il [math]p\text{-value}[/math] è pericolosamente vicino alla soglia di [math]0.05[/math]. Potrebbe essere un falso positivo.
  • Mancanza di contesto: Qual è la deviazione standard? Se è molto alta, quella differenza di 2 secondi è solo rumore.
  • Assenza di Effect Size: Senza il d di Cohen, non sappiamo se quei 2 secondi giustifichino i costi di migrazione dei server o di design.

Note finali per la Parte 1

Questa prima parte ci ha insegnato a non fidarci ciecamente di una funzione Python. Abbiamo visto che stats.ttest_ind è un’arma potente, ma va impugnata con la consapevolezza del Test di Welch e dell’Effect Size.

Pubblicità