Test de Newman-Keuls
Différence significatives entre moyennes
Test de Newman-Keuls, tests de Student en séries, Comparaisons post-hoc
Si j'ai plusieurs échantillons dont je souhaite comparer les moyennes, plusieurs approches sont possibles.
1- D'abord analyser la variance
L'analyse de la variance se fait avec les fonctions anova() ou aov(). Elle va permettre de voir, si des différences significatives ressortent.
Il faudra alors chercher quelles moyennes semblent se distinguer des autres. On va donc réaliser une comparaison post-hoc, un test qui se décide donc a posteriori et en fonction de l'analyse de la variance : méfiance donc.
INCONVÉNIENT : l'analyse de la variance peut passer à côté de différences réelles si les différences ne concernent qu'un nombre réduit de moyennes.
ATTENTION : une ANOVA doit être aussi validée (ce qu'on oublie souvent de faire par différents tests) : SKEWNESS (symétrie des courbes de densité), KURTOSIS (applatissement de la courbe de densité) et LEVENE (Démontrer que les variances des échantillons sont égales de façon robuste).
Remarque : il faudrait creuser les différences entre anova() et aov() : le 2ème semble pouvoir utiliser lm() de façon interne et peut donc s'en passer.
# Un jeu de données qui décrit de voitures
data(mtcars)
head(mtcars)
mtcars$carb[mtcars$carb>=4] <- 4
# Poyenne conso en fonction du nombre de carburateurs
result <- by(mtcars$mpg,mtcars$carb,mean)
linear_model <- lm(mtcars$mpg~mtcars$carb)
model <- anova(linear_model) ; model
On voit ici les "***" qui montre qu'il a bien une belle différence entre certaines de nos moyennes.
Analysis of Variance Table
Response: mtcars$mpg
Df Sum Sq Mean Sq F value Pr(>F)
mtcars$carb 1 462.81 462.81 20.934 7.706e-05 ***
Residuals 30 663.24 22.11
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Affichage du diagramme en barres
barplot(result,col="orange",lwd=2,main="Consommation en miles/gallon en fonction\ndu nombre de carburateurs",
names.arg =c(1:3,"4 ou plus"))
Reste à voir combien il y a de catégories de moyennes. Les voiture à 1 carburateur sont elles significativement différentes de celles à 2 carburateurs ?
2- Faire des tests de Student en série ?
C'est une approche brute de décoffrage : on va croiser tous les échantillons pour comparer leurs moyennes 2 à 2. On va ainsi identifier qui est différent de qui et pouvoir définir des catégories de moyennes.
AVANTAGE : C'est très fin. On pourra voir des différences qui n'auront pas été vues lors de l'ANOVA.
INCONVÉNIENT : On risque de voir comme significatives des différences du fait du hasard. En effet, sur un grand nombre d'échantillons, le hasard finira bien par nous sortir un échantillon qui contraste avec un autre. cf. ce lien externe qui revient sur ce problème.
DÉMARCHE : Il faut d'abord vérifier que les échantillons respectent la loi normal. S'ils suivent la loi normale, on pourra faire des tests de Student, sinon, il faudra faire des tests de Wilcoxon (comparaison des médianes, très robuste).
Remarque : Student, test paramétrique vs Wilcoxon, non paramétrique (pas d'hypothèse initiale de répartition).
2.1- Avec une boucle, Student 2 à 2 (déconseillé)
######################
# Tests croisés et systématique
######################
# Shapiro : si p-value < 0.05 => Loi non normale
by(mtcars$mpg,mtcars$carb,length)
by(mtcars$mpg,mtcars$carb,shapiro.test)
# Séries de tests : Wilcoxon si non normale, Student si loi normale suivi pour échantillons
modalités <- sort(unique(mtcars$carb))
for (i in 1:(length(modalités)-1)) {
for (j in (i+1):length(modalités)) {
temp0 <- mtcars$mpg[mtcars$carb == modalités[i]]
temp1 <- mtcars$mpg[mtcars$carb == modalités[j]]
#Choisir le test (ici Student) en changeant le #.
pval <- t.test(temp0,temp1)$p.value
#pval <- wilcox.test(temp0,temp1)$p.value
if (pval < 0.05) {
cat("Différence signif entre ",modalités[i]," et ",modalités[j],"avec pval : ",pval,"\n")
}
}
}
bp <- barplot(result,
col="orange",lwd=2,
main="Consommation en miles/gallon en fonction\ndu nombre de carburateurs",
names.arg =c(1:3,"4 ou plus"),
ylim=c(0,30))
text(bp, result+2, c("a","a","b","b"))
Indiquer les catégories par des lettres.
Revenir sur cette formation simple (PAGE DE FORMATION + EXEMPLE COMPLET).
2.2- Avec une fonction de systématisation (pairwise.t.test)
Il vaut mieux utiliser la fonction pairwise.t.test() (ou son pendant en wicoxon pairwise.wilcox.test()).
C'est plus simple et on tient compte de la tous les échantillons (ajustement de la p-value) pour éviter les différences faussement significatives dues au hasard.
data(mtcars)
mtcars$carb[mtcars$carb>=4] <- 4
pairwise.t.test(mtcars$mpg,mtcars$carb)-> mon_resultat : mon_resultat
Et voilà! tous les tests de Student ont été fait en une ligne (on peut changer aussi la méthode d'ajustement de la p-value en jouant sur les arguments de la fonction pariwise.t.test().
3- Appliquer un test de Newman-Keuls
Une possibilité est d'appliquer un test de Newman-Keuls qui permettra de définir les catégories de barres.
AVANTAGE : ce test (réputé plus puissant que le test des étendues de Tukey qui présente l'avantage de permettre de calculer la plus petite différence significative entre les échantillons (exemple ici)) tient compte de tous les échantillons pour éviter les différences faussement significatives. C'est un test robuste.
install.packages("agricolae") ; library(agricolae) # librairie nécessaire pour avoir la fonction.
model <- aov(mpg~carb,data=mtcars) ; model
SNK.test(model,"carb")
print(SNK.test(model,"carb", group=TRUE))
On voit bien ici que les 2 catégories a et b trouvés en faisant un long algorithme de Student en série donnent la même chose ici avec Newman-Keuls.
mpg groups
1 25.34286 a
2 22.40000 a
3 16.30000 b
4 16.05000 b