Test t di Welch: La Guida Pratica per Scegliere il Test Statistico Giusto (con Esempi in Python)

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Medie diverse- Non tirare a indovinare il test statistico

Immagina di aver appena concluso un test A/B su due versioni di una landing page. La versione B ha un tasso di conversione leggermente più alto.

Oppure, stai analizzando i dati di un esperimento e il gruppo trattato con un nuovo farmaco mostra una pressione sanguigna media inferiore. La domanda è sempre la stessa: questa differenza è reale o è solo frutto del caso?

Entrare nel mondo dei test di ipotesi può sembrare come aprire una cassetta degli attrezzi con decine di chiavi quasi identiche.

C’è il classico t-test di Student, il suo cugino più robusto, il test di Welch, e tutta una serie di alternative “non parametriche” per i casi difficili. Quale usare? E perché?

Welch e gli altri…

Una mappa pratica per orientarsi tra test t e alternative non parametriche

Ci sono momenti, in statistica, in cui la domanda sembra semplice: le medie di due gruppi sono diverse?

Poi ci si accorge che la risposta è un labirinto di varianti, ipotesi e test. C’è il t di Student classico, c’è il t di Welch, ci sono alternative non parametriche. E per ogni situazione – gruppi indipendenti, misure accoppiate, più di due campioni – serve la bussola giusta.

In questo articolo proviamo a costruire una mappa sintetica ma completa: non un manuale accademico, ma una guida operativa per capire quando usare Welch e quando scegliere altro.

1. Due gruppi indipendenti: il terreno di Welch

È lo scenario più comune: due gruppi distinti, ad esempio la pressione sanguigna nei maschi vs femmine, o la risposta a un farmaco tra gruppo A e gruppo B.

Ipotesi da verificare:

[math]H_0: \mu_1 = \mu_2[/math]

Le opzioni sul tavolo:

  • t di Student (pooled): funziona se i due gruppi hanno varianze simili.
  • t di Welch: valido anche con varianze diverse, è il default in R (t.test(..., var.equal=FALSE)) e in Python (scipy.stats.ttest_ind(..., equal_var=False)).
  • Mann–Whitney U: alternativa non parametrica, utile se i dati sono ordinali o molto lontani dalla normalità.

👉 Regola pratica: se i campioni sono indipendenti e la variabilità non è uguale, usa Welch. Se le varianze sembrano simili, entrambi i test vanno bene, ma Welch non ti costa nulla.

2. Due campioni dipendenti: prima e dopo

Qui non si tratta più di due gruppi distinti, ma dello stesso soggetto misurato in condizioni diverse (es. “prima” e “dopo” un trattamento).

Ipotesi:

[math]H_0: \text{media delle differenze} = 0[/math]

Le opzioni:

  • t accoppiato: se le differenze seguono (circa) una distribuzione normale.
  • Wilcoxon signed-rank: se le differenze sono lontane dalla normalità o se i dati sono ordinali.

👉 Nota operativa: spesso il Wilcoxon ha più potenza del t quando le distribuzioni sono fortemente asimmetriche.

3. Un campione vs valore noto

Vuoi confrontare la media di un gruppo con un valore di riferimento (es. pressione media vs 120 mmHg).

  • One-sample t: valido se il campione è normale.
  • Wilcoxon signed-rank o test del segno: alternative non parametriche se la normalità è dubbia.

4. Più di due gruppi

Quando i gruppi diventano tre o più, non basta più il test t.

  • ANOVA a una via: se le varianze sono omogenee.
  • Welch’s ANOVA: se le varianze sono eterogenee.
  • Kruskal–Wallis: alternativa non parametrica, utile con dati ordinali o distribuzioni problematiche.
  • Misure ripetute: servono ANOVA per misure ripetute o modelli misti.

5. Perché Welch è diventato lo “standard moderno”

Storicamente il test t “pooled” era l’opzione principale. Oggi, però, Welch è preferito quasi ovunque. Perché?

  • Robustezza: controlla meglio il livello di significatività anche con varianze molto diverse.
  • Potenza: è uguale o superiore a quella del t classico.
  • Praticità: elimina il fastidioso “doppio test” (prima verificare omoscedasticità, poi decidere il t).
  • Neutralità: anche quando le varianze sono uguali, non perde praticamente nulla.

👉 Tradotto: se hai due campioni indipendenti, la prima scelta oggi è Welch.

Forse potrebbe interessarti anche:  ArviZ: Analisi Bayesiana e Diagnostica MCMC Essenziale con Python

6. Checklist operativa (flow-chart testuale)

Uno o due campioni?

  • Uno → one-sample t o Wilcoxon.
  • Due → vai al punto 2.

Indipendenti o accoppiati?

  • Accoppiati → paired t o Wilcoxon.
  • Indipendenti → vai al punto 3.

Tipo di variabile:

  • Quantitativa continua → prosegui.
  • Ordinale/Likert → Mann–Whitney.

Normalità:

  • Se n è grande (≥30–40), i test t sono robusti.
  • Se n è piccolo e distribuzione sospetta → non parametrico.

Varianze (solo se indipendenti):

  • Simili → t Student o Welch.
  • Diverse → Welch.

7. Esempio numerico

Gruppo A: 8, 9, 10, 11, 12 → varianza [math]s^2 = 2,5[/math]

Gruppo B: 20, 22, 24, 26, 28 → varianza [math]s^2 = 10[/math]

Test di Levene: [math]p = 0,02[/math]

[math]p = 0,02 \to \text{varianze diverse.}[/math]

t di Welch:

[math]\displaystyle t = -9,18, \, gl \approx 5,7, \, p < 0,001.[/math]

t di Student (pooled):

stesso valore di [math]t[/math], ma con [math]gl = 8[/math]. L’errore di tipo I reale, però, sale a ~0,08 invece di 0,05.

👉 Morale: Welch ti protegge dal falso positivo.

Approfondimento sui test: teoria ed esempi pratici

1. t di Student (pooled)

  • Ipotesi: [math]H_0: \mu_1 = \mu_2[/math]
  • Assunzioni:
    • Campioni indipendenti
    • Varianze uguali
    • Dati circa normali
  • Formula: [math]\displaystyle t = \frac{\bar{x}_1 – \bar{x}_2}{s_p \sqrt{\frac{1}{n_1} + \frac{1}{n_2}}} \quad\text{con}\quad s_p^2 = \frac{(n_1-1)s_1^2 + (n_2-1)s_2^2}{n_1+n_2-2}[/math]
  • Esempio pratico: Supponiamo di confrontare l’altezza media di 20 maschi e 20 femmine. Se le varianze sono simili (test di Levene non significativo), il t pooled è appropriato.

2. t di Welch

  • Ipotesi: [math]H_0: \mu_1 = \mu_2[/math]
  • Assunzioni:
    • Campioni indipendenti
    • Non richiede varianze uguali
    • Dati circa normali
  • Formula (semplificata): [math]t = \frac{\bar{x}_1 – \bar{x}_2}{\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}}}[/math] I gradi di libertà sono stimati con la formula di Welch–Satterthwaite.
  • Esempio pratico: Farmaco A ([math]n=12[/math], varianza=[math]5[/math]), Farmaco B ([math]n=15[/math], varianza=[math]20[/math]). Le varianze sono diverse → si usa Welch. Risultato: più affidabile, evita falsi positivi.

3. Mann–Whitney U

  • Ipotesi: le distribuzioni dei due gruppi sono identiche (spesso interpretato come “mediane uguali”).
  • Assunzioni:
    • Campioni indipendenti
    • Dati ordinali o non normali
  • Idea del test: confronta i ranghi combinati, non le medie.
  • Esempio pratico: Soddisfazione su scala Likert (1–5) tra due gruppi di clienti. Non ha senso fare una media aritmetica, quindi si usa Mann–Whitney.

4. t accoppiato

  • Ipotesi: [math]H_0: \mu_d = 0[/math], dove [math]d = x_{\text{prima}} – x_{\text{dopo}}[/math].
  • Assunzioni:
    • Differenze normalmente distribuite
  • Formula: [math]t = \frac{\bar{d}}{s_d / \sqrt{n}}[/math]
  • Esempio pratico: Misuro la pressione di 10 pazienti prima e dopo un farmaco. Se le differenze sono distribuite normalmente, applico il t accoppiato per testare l’efficacia.

5. Wilcoxon signed-rank

  • Ipotesi: la mediana delle differenze = 0.
  • Assunzioni:
    • Campioni appaiati
    • Non richiede normalità
  • Idea del test: ordina le differenze in valore assoluto e assegna segni → confronta se i segni positivi e negativi sono bilanciati.
  • Esempio pratico: Voto di gradimento di uno stesso gruppo prima e dopo un workshop (scala 1–10, distribuzione asimmetrica).

6. One-sample t

  • Ipotesi: [math]H_0: \mu = \mu_0[/math].
  • Assunzioni:
    • Dati normali.
  • Formula: [math]t = \frac{\bar{x} – \mu_0}{s/\sqrt{n}}[/math]
  • Esempio pratico: Campione di 30 studenti, altezza media = 172 cm. Confronto con valore noto 170 cm.

7. Test del segno

  • Ipotesi: la mediana delle differenze = 0.
  • Assunzioni:
    • Dati appaiati
    • Non richiede normalità
  • Idea del test: conta quante differenze sono positive vs negative.
  • Esempio pratico: Confronto “prima/dopo” sul tempo impiegato a completare un compito, con distribuzione estremamente asimmetrica.

8. ANOVA e varianti

  • ANOVA classica: più di due gruppi, varianze uguali.
  • Welch’s ANOVA: più di due gruppi, varianze diverse.
  • Kruskal–Wallis: non parametrico, confronta ranghi.
  • Esempio pratico: Confronto diete A, B, C.
    • Se i dati sono normali e omoschedastici → ANOVA.
    • Se varianze diverse → Welch’s ANOVA.
    • Se distribuzione non normale → Kruskal–Wallis.

🐍 Una diagnostica automatica per scegliere il test statistico

Finora abbiamo costruito una checklist logica e un diagramma decisionale per capire quando usare il t-test di Welch o le sue alternative.
Ma nella pratica, quando abbiamo i dati in un file o in un DataFrame, può essere utile avere uno strumento automatico che ci guidi nella scelta del test.

Forse potrebbe interessarti anche:  Outlier: Cosa Sono, Come Trovarli e Rimuoverli con Pandas (Metodi IQR e Z-score)

Obiettivi dello snippet

Lo snippet Python che segue ha tre scopi principali:

  1. Automatizzare la diagnosi – dato un dataset, il programma controlla:

    • numero di campioni,

    • indipendenza o appaiamento,

    • normalità delle distribuzioni,

    • omogeneità delle varianze.

  2. Suggerire il test corretto – restituisce la raccomandazione su quale test statistico applicare:

    • t di Student, t di Welch, Wilcoxon, Mann–Whitney U, ANOVA, Kruskal–Wallis, ecc.

  3. Fornire un output leggibile – il risultato non è un semplice “vero/falso”, ma una mini–diagnosi in linguaggio naturale, utile per studenti, data analyst e ricercatori.

Creiamo il dataset fittizio:

import pandas as pd
import numpy as np

np.random.seed(42)

# 1. Un campione (pressione sanguigna rispetto a 120)
pressione = np.random.normal(122, 5, 30)

# 2. Due campioni indipendenti (colesterolo maschi vs femmine)
maschi = np.random.normal(200, 15, 25)
femmine = np.random.normal(190, 12, 22)

# 3. Due campioni appaiati (prima e dopo dieta sugli stessi soggetti)
prima_dieta = np.random.normal(85, 8, 20)
dopo_dieta = prima_dieta - np.random.normal(5, 3, 20)  # effetto medio -5 kg

# 4. Tre campioni indipendenti (3 tipi di dieta e perdita di peso)
dieta_A = np.random.normal(4, 1, 15)
dieta_B = np.random.normal(6, 1.2, 15)
dieta_C = np.random.normal(5, 0.8, 15)

# Find the maximum length among all arrays
max_len = max(len(pressione), len(maschi), len(femmine), len(prima_dieta), len(dopo_dieta), len(dieta_A), len(dieta_B), len(dieta_C))

# Pad shorter arrays with NaN to match the maximum length
def pad_array(arr, length):
    return np.pad(arr.astype(float), (0, length - len(arr)), 'constant', constant_values=np.nan)

pressione_padded = pad_array(pressione, max_len)
maschi_padded = pad_array(maschi, max_len)
femmine_padded = pad_array(femmine, max_len)
prima_dieta_padded = pad_array(prima_dieta, max_len)
dopo_dieta_padded = pad_array(dopo_dieta, max_len)
dieta_A_padded = pad_array(dieta_A, max_len)
dieta_B_padded = pad_array(dieta_B, max_len)
dieta_C_padded = pad_array(dieta_C, max_len)


# Creazione DataFrame
df = pd.DataFrame({
    "pressione": pressione_padded,
    "colesterolo_maschi": maschi_padded,
    "colesterolo_femmine": femmine_padded,
    "peso_prima_dieta": prima_dieta_padded,
    "peso_dopo_dieta": dopo_dieta_padded,
    "dieta_A": dieta_A_padded,
    "dieta_B": dieta_B_padded,
    "dieta_C": dieta_C_padded
})

df.head()

Come usare il dataset

Il dataset è strutturato in modo da coprire i casi più comuni, dal confronto di un singolo campione con un valore noto fino all’analisi di più di due gruppi. L’obiettivo è farti capire che a ogni scenario corrisponde un test specifico.

Mappatura dei test statistici

Ecco una mappa dettagliata che collega ogni colonna del tuo dataset al test statistico appropriato e all’ipotesi che puoi verificare.

1. Test a un campione

  • Colonna: pressione
  • Scenario: Confrontare la pressione media del campione con un valore di riferimento (nell’esempio, 120 mmHg).
  • Ipotesi principale: L’ipotesi nulla () è che la media della pressione del campione sia uguale a 120 mmHg ().
  • Test da usare: Usa il test t a un campione se i dati sono distribuiti normalmente. Se la distribuzione è molto diversa dalla normalità, puoi ricorrere al test di Wilcoxon (se la mediana è un indicatore più appropriato) o al test del segno.

2. Test tra due gruppi indipendenti

  • Colonne: colesterolo_maschi e colesterolo_femmine
  • Scenario: Confrontare le medie di due gruppi indipendenti, in questo caso, il colesterolo nei maschi e nelle femmine.
  • Ipotesi principale: L’ipotesi nulla () è che la media del colesterolo nei maschi sia uguale a quella delle femmine ().
  • Test da usare: Se le varianze dei due gruppi sono simili (puoi verificarlo con un test di Levene), puoi usare il t di Student. Se le varianze sono diverse, come spesso accade, la scelta migliore e più robusta è il t di Welch. Se i dati non sono normali, l’alternativa non parametrica è il test di Mann-Whitney U.

3. Test tra due campioni appaiati

  • Colonne: peso_prima_dieta e peso_dopo_dieta
  • Scenario: Misurare un cambiamento nello stesso gruppo di individui, per esempio il peso prima e dopo una dieta.
  • Ipotesi principale: L’ipotesi nulla () è che la media delle differenze tra il peso iniziale e quello finale sia zero ().
  • Test da usare: Se le differenze tra le misurazioni sono distribuite normalmente, usa il t-test accoppiato. In caso contrario, l’alternativa non parametrica è il test dei ranghi con segno di Wilcoxon.
Forse potrebbe interessarti anche:  R Quadrato vs Correlazione: Differenza, Calcolo e Guida Pratica

4. Test tra più di due gruppi

  • Colonne: dieta_A, dieta_B e dieta_C
  • Scenario: Confrontare le medie di tre o più gruppi, come l’effetto di diverse diete sul peso.
  • Ipotesi principale: L’ipotesi nulla () è che le medie dei tre gruppi siano tutte uguali ().
  • Test da usare: Se i dati sono normali e le varianze omogenee, l’opzione è l’ANOVA a una via. Se le varianze sono diverse, come suggerito dal tuo testo, si usa la Welch ANOVA. Se la distribuzione dei dati non è normale, usa l’equivalente non parametrico, il test di Kruskal-Wallis.

Lo snippet “diagnostico”:

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

# =============================
# Dataset fittizio (pressione sanguigna)
# =============================
np.random.seed(42)

# Gruppo A (maschi, sd più alta)
group_A = np.random.normal(loc=125, scale=12, size=30)
# Gruppo B (femmine, sd più bassa)
group_B = np.random.normal(loc=120, scale=8, size=28)

df = pd.DataFrame({
    "valore": np.concatenate([group_A, group_B]),
    "gruppo": ["A"]*len(group_A) + ["B"]*len(group_B)
})

# =============================
# Funzione diagnostica
# =============================
def diagnostica_test(df, valore_col="valore", gruppo_col="gruppo", paired=False):
    """
    Determina quale test statistico usare per confrontare gruppi.
    """
    gruppi = [g[valore_col].values for _, g in df.groupby(gruppo_col)]
    
    if len(gruppi) == 1:
        # Caso: un solo campione vs valore noto
        x = gruppi[0]
        shapiro_p = stats.shapiro(x).pvalue
        if shapiro_p > 0.05:
            return "One-sample t-test (dati ~ normali)"
        else:
            return "Test non parametrico (Wilcoxon o test del segno)"
    
    elif len(gruppi) == 2:
        x, y = gruppi
        
        if paired:
            # Caso: dati appaiati
            diff = x[:min(len(x), len(y))] - y[:min(len(x), len(y))]
            shapiro_p = stats.shapiro(diff).pvalue
            if shapiro_p > 0.05:
                return "Paired t-test (differenze ~ normali)"
            else:
                return "Wilcoxon signed-rank test (differenze non normali)"
        
        else:
            # Caso: due gruppi indipendenti
            shapiro_x = stats.shapiro(x).pvalue
            shapiro_y = stats.shapiro(y).pvalue
            normali = (shapiro_x > 0.05) and (shapiro_y > 0.05)
            
            levene_p = stats.levene(x, y).pvalue
            var_equal = levene_p > 0.05
            
            if normali:
                if var_equal:
                    return "t-test di Student (varianze simili)"
                else:
                    return "t-test di Welch (varianze diverse)"
            else:
                return "Mann-Whitney U test (non parametrico)"
    
    else:
        # Caso: più di due gruppi
        norm_p = [stats.shapiro(g).pvalue for g in gruppi]
        normali = all(p > 0.05 for p in norm_p)
        
        levene_p = stats.levene(*gruppi).pvalue
        var_equal = levene_p > 0.05
        
        if normali:
            if var_equal:
                return "ANOVA one-way (varianze simili)"
            else:
                return "Welch ANOVA (varianze diverse)"
        else:
            return "Kruskal-Wallis test (non parametrico)"

# =============================
# ESEMPIO DIAGNOSTICA
# =============================
risultato = diagnostica_test(df, valore_col="valore", gruppo_col="gruppo", paired=False)
print("Diagnosi statistica:", risultato)

🔎 Output atteso (con il nostro dataset)

Diagnosi statistica: t-test di Student (varianze simili)

Per far scattare la raccomandazione “t-test di Welch”, basterebbe aumentare la differenza tra le deviazioni standard nel codice di generazione dati (es. scale=15 vs scale=5).

8. Una frase per ricordare tutto

Se devi confrontare le medie di due gruppi indipendenti, scegli Welch: funziona con varianze uguali o diverse, è robusto, non richiede pre-test. Riserva il t di Student pooled solo a casi in cui sei sicuro di avere varianze identiche e vuoi spremere un briciolo di potenza in più. Se la normalità crolla, passa a un test non parametrico.

Pubblicità