In realtà non è molto difficile gestire l'eteroscedasticità in semplici modelli lineari (ad esempio, modelli ANOVA a una o due vie).
Robustezza di ANOVA
In primo luogo, come altri hanno notato, l'ANOVA è incredibilmente robusto per le deviazioni dall'assunzione di varianze uguali, specialmente se si dispone di dati approssimativamente bilanciati (uguale numero di osservazioni in ciascun gruppo). I test preliminari su varianze uguali, d'altro canto, non lo sono (sebbene il test di Levene sia molto migliore del test F comunemente insegnato nei libri di testo). Come diceva George Box:
Effettuare il test preliminare sulle varianze è piuttosto come mettersi in mare su una barca a remi per scoprire se le condizioni sono sufficientemente calme per consentire a un transatlantico di lasciare il porto!
Anche se ANOVA è molto robusto, poiché è molto facile tenere conto dell'eteroscedaticità, ci sono poche ragioni per non farlo.
Test non parametrici
Se sei veramente interessato alle differenze di mezzi , i test non parametrici (ad esempio il test di Kruskal – Wallis) non servono davvero. Fanno le differenze tra i gruppi di test, ma lo fanno senza differenze di prova generale in mezzo.
Dati di esempio
Generiamo un semplice esempio di dati in cui si vorrebbe usare ANOVA, ma in cui l'assunzione di varianze uguali non è vera.
set.seed(1232)
pop = data.frame(group=c("A","B","C"),
mean=c(1,2,5),
sd=c(1,3,4))
d = do.call(rbind, rep(list(pop),13))
d$x = rnorm(nrow(d), d$mean, d$sd)
Abbiamo tre gruppi, con (chiare) differenze sia nella media che nella varianza:
stripchart(x ~ group, data=d)
ANOVA
Non sorprende che un normale ANOVA lo gestisca abbastanza bene:
> mod.aov = aov(x ~ group, data=d)
> summary(mod.aov)
Df Sum Sq Mean Sq F value Pr(>F)
group 2 199.4 99.69 13.01 5.6e-05 ***
Residuals 36 275.9 7.66
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Quindi, quali gruppi differiscono? Usiamo il metodo HSD di Tukey:
> TukeyHSD(mod.aov)
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = x ~ group, data = d)
$group
diff lwr upr p adj
B-A 1.736692 -0.9173128 4.390698 0.2589215
C-A 5.422838 2.7688327 8.076843 0.0000447
C-B 3.686146 1.0321403 6.340151 0.0046867
Con un valore P di 0,26, non possiamo rivendicare alcuna differenza (in media) tra il gruppo A e B. E anche se non prendessimo in considerazione il fatto che abbiamo fatto tre confronti, non otterremmo una P bassa - valore ( P = 0.12):
> summary.lm(mod.aov)
[…]
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.5098 0.7678 0.664 0.511
groupB 1.7367 1.0858 1.599 0.118
groupC 5.4228 1.0858 4.994 0.0000153 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.768 on 36 degrees of freedom
Perché? Sulla base della trama, non v'è una differenza abbastanza chiaro. Il motivo è che ANOVA assume varianze uguali in ciascun gruppo e stima una deviazione standard comune di 2,77 (indicata come "Errore standard residuo" nelsummary.lm
tabella, oppure è possibile ottenerla prendendo la radice quadrata del quadrato medio residuo (7,66) nella tabella ANOVA).
Ma il gruppo A ha una deviazione standard (della popolazione) di 1, e questa sopravvalutazione di 2,77 rende (inutilmente) difficile ottenere risultati statisticamente significativi, cioè abbiamo un test con (troppo) bassa potenza.
'ANOVA' con varianze ineguali
Quindi, come adattare un modello adeguato, che tenga conto delle differenze di varianza? È facile in R:
> oneway.test(x ~ group, data=d, var.equal=FALSE)
One-way analysis of means (not assuming equal variances)
data: x and group
F = 12.7127, num df = 2.000, denom df = 19.055, p-value = 0.0003107
Quindi, se si desidera eseguire un semplice "ANOVA" unidirezionale in R senza assumere scostamenti uguali, utilizzare questa funzione. È fondamentalmente un'estensione del (Welch) t.test()
per due campioni con varianze ineguali.
Sfortunatamente, non funziona con TukeyHSD()
(o la maggior parte delle altre funzioni che usi sugli aov
oggetti), quindi anche se siamo abbastanza sicuri che ci siano differenze di gruppo, non sappiamo dove siano.
Modellare l'eteroscedasticità
La soluzione migliore è modellare esplicitamente le varianze. Ed è molto facile in R:
> library(nlme)
> mod.gls = gls(x ~ group, data=d,
weights=varIdent(form= ~ 1 | group))
> anova(mod.gls)
Denom. DF: 36
numDF F-value p-value
(Intercept) 1 16.57316 0.0002
group 2 13.15743 0.0001
Differenze ancora significative, ovviamente. Ma ora anche le differenze tra i gruppi A e B sono diventate staticamente significative ( P = 0,025):
> summary(mod.gls)
Generalized least squares fit by REML
Model: x ~ group
[…]
Variance function:
Structure: Different standard
deviations per stratum
Formula: ~1 | group
Parameter estimates:
A B C
1.000000 2.444532 3.913382
Coefficients:
Value Std.Error t-value p-value
(Intercept) 0.509768 0.2816667 1.809829 0.0787
groupB 1.736692 0.7439273 2.334492 0.0253
groupC 5.422838 1.1376880 4.766542 0.0000
[…]
Residual standard error: 1.015564
Degrees of freedom: 39 total; 36 residual
Quindi usare un modello appropriato aiuta! Si noti inoltre che otteniamo stime delle deviazioni standard (relative). La deviazione standard stimata per il gruppo A può essere trovata nella parte inferiore del, risultati, 1.02. La deviazione standard stimata del gruppo B è 2,44 volte questa, o 2,48, e la deviazione standard stimata del gruppo C è simile a 3,97 (digitare intervals(mod.gls)
per ottenere intervalli di confidenza per le deviazioni standard relative dei gruppi B e C).
Correzione per più test
Tuttavia, dovremmo davvero correggere più test. Questo è facile usando la libreria 'multcomp'. Sfortunatamente, non ha il supporto integrato per gli oggetti 'gls', quindi dovremo prima aggiungere alcune funzioni di supporto:
model.matrix.gls <- function(object, ...)
model.matrix(terms(object), data = getData(object), ...)
model.frame.gls <- function(object, ...)
model.frame(formula(object), data = getData(object), ...)
terms.gls <- function(object, ...)
terms(model.frame(object),...)
Ora mettiamoci al lavoro:
> library(multcomp)
> mod.gls.mc = glht(mod.gls, linfct = mcp(group = "Tukey"))
> summary(mod.gls.mc)
[…]
Linear Hypotheses:
Estimate Std. Error z value Pr(>|z|)
B - A == 0 1.7367 0.7439 2.334 0.0480 *
C - A == 0 5.4228 1.1377 4.767 <0.001 ***
C - B == 0 3.6861 1.2996 2.836 0.0118 *
Differenza statisticamente significativa ancora tra il gruppo A e il gruppo B! ☺ E possiamo anche ottenere intervalli di confidenza (simultanei) per le differenze tra i gruppi:
> confint(mod.gls.mc)
[…]
Linear Hypotheses:
Estimate lwr upr
B - A == 0 1.73669 0.01014 3.46324
C - A == 0 5.42284 2.78242 8.06325
C - B == 0 3.68615 0.66984 6.70245
Usando un modello approssimativamente (qui esattamente) corretto, possiamo fidarci di questi risultati!
Si noti che per questo semplice esempio, i dati per il gruppo C non aggiungono realmente alcuna informazione sulle differenze tra il gruppo A e B, poiché modelliamo sia medie separate che deviazioni standard per ciascun gruppo. Avremmo potuto usare t -test a coppie corretti per confronti multipli:
> pairwise.t.test(d$x, d$group, pool.sd=FALSE)
Pairwise comparisons using t tests with non-pooled SD
data: d$x and d$group
A B
B 0.03301 -
C 0.00098 0.02032
P value adjustment method: holm
Tuttavia, per i modelli più complicati, ad esempio modelli a due vie o modelli lineari con molti predittori, l'utilizzo di GLS (minimi quadrati generalizzati) e la modellazione esplicita delle funzioni di varianza è la soluzione migliore.
E la funzione di varianza non deve essere semplicemente una costante diversa in ciascun gruppo; possiamo imporre struttura su di esso. Ad esempio, possiamo modellare la varianza come una potenza della media di ciascun gruppo (e quindi solo per stimare un parametro, l'esponente), o forse come logaritmo di uno dei predittori nel modello. Tutto questo è molto semplice con GLS (e gls()
in R).
I minimi quadrati generalizzati sono l'IMHO una tecnica di modellistica statistica molto poco utilizzata. Invece di preoccuparti delle deviazioni dalle ipotesi del modello, modella quelle deviazioni!
R
, può essere utile leggere qui la mia risposta: Alternative all'ANOVA a senso unico per i dati eteroscedastici , che discute di alcuni di questi problemi.