Avant propos
La base de données utilisée en fil rouge de ce TP regroupe des informations sur les joueurs de football des 5 grands championnats européens (France, Italie, Allemagne, Espagne, Angleterre), regroupés par club, entre les années 2009 et 2016. L’objectif de cette étude de cas est de mener l’analyse statistique d’une base de données relativement riche en information de bout en bout, depuis le netoyage, la prise en main, jusqu’à l’utilisation de méthodes de visualisation et d’analyse plus sophistiquées (ACP, AFC, Clustering), précédemment vues en cours. Cette étude est prévue pour s’étendre sur une dizaine d’heures en ‘autonomie dirigée’, permettant de balayer au maximum les différentes approches et méthodes par vous même. L’évaluation finale consistera en une analyse (réduite) du même type, d’environ 1h30, sur une autre base de données. De nombreuses approches différentes pouvant être valable, il n’y a pas de réponse universelle et de correction unique de cette analyse, n’hésitez donc pas à essayer des choses et prendre des initiatives, c’est tout l’objectif de ce cours (cela sera valorisé dans l’évaluation). Pour tout de même offrir un support commun rassemblant, pour nos TPs à distance, une trame commune détaillant l’utilisation de quelques commandes, packages, et fonctions importantes, ce document sera mise à jour au fûr et à mesure de vos suggestions. Le notebook sera accessible dans sa version courante sur Moodle.
Comme pour toute étude, la première étape consiste en l’importation des packages et des données. Par convention, nous utiliserons dans la mesure du possible un nom générique pour les données brutes (raw_db), différent du tibble (ou dataframe) de travail (db) sur lequel seront faites les analyses.
library(tidyverse)
library(gridExtra)
library(FactoMineR)
library(factoextra)
#
= read_csv("C:/Users/user/Google Drive/Travail/Enseignement/STID/2A/ADD/Codes R/Donnees/DB_Football_2009_2016_classif_4labels.csv")
raw_db
str(raw_db)
## tibble [21,551 x 21] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ R : num [1:21551] 13 1 19 2 3 4 5 6 7 8 ...
## $ année (début du championnat): num [1:21551] 2016 2016 2016 2016 2016 ...
## $ Player : chr [1:21551] "Loic Badiashile" "Fabinho" "João Moutinho" "Thomas Lemar" ...
## $ Club : chr [1:21551] "Monaco" "Monaco" "Monaco" "Monaco" ...
## $ âge : chr [1:21551] " 19" " 23" " 30" " 21" ...
## $ Position : chr [1:21551] "GK" "D" "M" "F" ...
## $ Position 2 : chr [1:21551] NA "DMC" NA NA ...
## $ Position 3 : chr [1:21551] NA NA NA NA ...
## $ CM : num [1:21551] 186 188 170 170 184 177 172 190 173 183 ...
## $ KG : num [1:21551] 80 78 61 58 70 72 63 80 64 72 ...
## $ Apps : chr [1:21551] "0(1)" "33(4)" "19(12)" "28(6)" ...
## $ Mins : num [1:21551] 45 3071 1768 2612 91 ...
## $ Goals : num [1:21551] 0 9 2 9 1 21 6 0 8 0 ...
## $ Assists : num [1:21551] 0 1 4 10 0 5 2 0 9 5 ...
## $ Yel : num [1:21551] 0 8 0 1 0 2 1 1 3 0 ...
## $ Red : num [1:21551] 0 0 0 0 0 0 0 0 0 0 ...
## $ SpG : num [1:21551] 0 0.8 0.6 1.7 2 2.8 1.8 1 1.6 0.4 ...
## $ PS% : num [1:21551] 85 84.4 85.2 82.8 76.5 78.9 76.1 67.6 81.1 79.3 ...
## $ AerialsWon : num [1:21551] 0 1.8 0.5 0.3 2 1.4 0.3 1 0.5 2.1 ...
## $ MotM : num [1:21551] 0 2 2 5 1 3 1 0 3 0 ...
## $ Rating : num [1:21551] 7.16 7.51 6.92 7.48 7.42 7.38 7.35 7.31 7.29 7.29 ...
## - attr(*, "spec")=
## .. cols(
## .. R = col_double(),
## .. `année (début du championnat)` = col_double(),
## .. Player = col_character(),
## .. Club = col_character(),
## .. âge = col_character(),
## .. Position = col_character(),
## .. `Position 2` = col_character(),
## .. `Position 3` = col_character(),
## .. CM = col_double(),
## .. KG = col_double(),
## .. Apps = col_character(),
## .. Mins = col_double(),
## .. Goals = col_double(),
## .. Assists = col_double(),
## .. Yel = col_double(),
## .. Red = col_double(),
## .. SpG = col_double(),
## .. `PS%` = col_double(),
## .. AerialsWon = col_double(),
## .. MotM = col_double(),
## .. Rating = col_double()
## .. )
Nous pouvons immédiatement remarquer que toutes les variables ont un type cohérent, sauf la variable âge qui est character putôt que numeric. Cette particularité est dûe à un soucis (très classique) de remplissage de la base de données, où un espace invisible s’est glissé avant chaque chiffre dans la colonne des âges. Un premier travail est donc nécessaire pour supprimer cet espace inutile et retransformer les âges en une variable numérique, comme cela est fait ci-dessous. De plus, nous allons aussi prendre la liberté de supprimer la première variable R, qui est tout à fait non informative.
= raw_db %>%
db select(- R) %>% # Suppress the useless column 'R'
mutate(âge = gsub("[[:space:]]", "", âge) %>% as.numeric) # Remove the spaces
str(db)
## tibble [21,551 x 20] (S3: tbl_df/tbl/data.frame)
## $ année (début du championnat): num [1:21551] 2016 2016 2016 2016 2016 ...
## $ Player : chr [1:21551] "Loic Badiashile" "Fabinho" "João Moutinho" "Thomas Lemar" ...
## $ Club : chr [1:21551] "Monaco" "Monaco" "Monaco" "Monaco" ...
## $ âge : num [1:21551] 19 23 30 21 21 31 21 24 23 21 ...
## $ Position : chr [1:21551] "GK" "D" "M" "F" ...
## $ Position 2 : chr [1:21551] NA "DMC" NA NA ...
## $ Position 3 : chr [1:21551] NA NA NA NA ...
## $ CM : num [1:21551] 186 188 170 170 184 177 172 190 173 183 ...
## $ KG : num [1:21551] 80 78 61 58 70 72 63 80 64 72 ...
## $ Apps : chr [1:21551] "0(1)" "33(4)" "19(12)" "28(6)" ...
## $ Mins : num [1:21551] 45 3071 1768 2612 91 ...
## $ Goals : num [1:21551] 0 9 2 9 1 21 6 0 8 0 ...
## $ Assists : num [1:21551] 0 1 4 10 0 5 2 0 9 5 ...
## $ Yel : num [1:21551] 0 8 0 1 0 2 1 1 3 0 ...
## $ Red : num [1:21551] 0 0 0 0 0 0 0 0 0 0 ...
## $ SpG : num [1:21551] 0 0.8 0.6 1.7 2 2.8 1.8 1 1.6 0.4 ...
## $ PS% : num [1:21551] 85 84.4 85.2 82.8 76.5 78.9 76.1 67.6 81.1 79.3 ...
## $ AerialsWon : num [1:21551] 0 1.8 0.5 0.3 2 1.4 0.3 1 0.5 2.1 ...
## $ MotM : num [1:21551] 0 2 2 5 1 3 1 0 3 0 ...
## $ Rating : num [1:21551] 7.16 7.51 6.92 7.48 7.42 7.38 7.35 7.31 7.29 7.29 ...
Nous avons bien le type voulu à présent, et pouvons donc passer à l’exploration à proprement dite, après un premier coup d’oeil général sur les différentes variables.
summary(db)
## année (début du championnat) Player Club
## Min. :2009 Length:21551 Length:21551
## 1st Qu.:2011 Class :character Class :character
## Median :2012 Mode :character Mode :character
## Mean :2013
## 3rd Qu.:2015
## Max. :2016
## âge Position Position 2 Position 3
## Min. :16.00 Length:21551 Length:21551 Length:21551
## 1st Qu.:26.00 Class :character Class :character Class :character
## Median :30.00 Mode :character Mode :character Mode :character
## Mean :29.97
## 3rd Qu.:33.00
## Max. :47.00
## CM KG Apps Mins
## Min. :159 Min. : 52.00 Length:21551 Min. : 1
## 1st Qu.:178 1st Qu.: 72.00 Class :character 1st Qu.: 382
## Median :182 Median : 76.00 Mode :character Median :1208
## Mean :182 Mean : 76.49 Mean :1325
## 3rd Qu.:186 3rd Qu.: 81.00 3rd Qu.:2174
## Max. :203 Max. :104.00 Max. :3420
## Goals Assists Yel Red
## Min. : 0.000 Min. : 0.000 Min. : 0.000 Min. :0.0000
## 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.:0.0000
## Median : 0.000 Median : 0.000 Median : 2.000 Median :0.0000
## Mean : 1.766 Mean : 1.231 Mean : 2.697 Mean :0.1605
## 3rd Qu.: 2.000 3rd Qu.: 2.000 3rd Qu.: 4.000 3rd Qu.:0.0000
## Max. :50.000 Max. :20.000 Max. :18.000 Max. :5.0000
## SpG PS% AerialsWon MotM
## Min. :0.0000 Min. : 0.00 Min. :0.0000 Min. : 0.0000
## 1st Qu.:0.2000 1st Qu.: 70.90 1st Qu.:0.3000 1st Qu.: 0.0000
## Median :0.6000 Median : 77.50 Median :0.7000 Median : 0.0000
## Mean :0.7747 Mean : 75.31 Mean :0.9607 Mean : 0.6715
## 3rd Qu.:1.1000 3rd Qu.: 82.70 3rd Qu.:1.4000 3rd Qu.: 1.0000
## Max. :7.4000 Max. :100.00 Max. :9.5000 Max. :25.0000
## Rating
## Min. : 3.700
## 1st Qu.: 6.430
## Median : 6.710
## Mean : 6.701
## 3rd Qu.: 6.960
## Max. :10.000
Pour commencer, nous pouvons par exemple étudier les différences morphologiques des différents postes, pour mieux appréhender nos données, et offrir un premier éclairage facile et à priori attendu dans ce contexte. Par exemple, la réparition des tailles par poste nous montre que les gardiens, et dans une moindre mesure les défenseurs semblent plus grands que leurs partenaires (N’hésitez pas essayer différente représentations graphiques, ici boxplots et violon plots).
= ggplot(db) + geom_boxplot(aes(x = Position, y = CM, color = Position)) + theme_classic() + labs(title = "Boxplot des tailles par poste")
gg1
= ggplot(db) + geom_violin(aes(x = Position, y = KG, color = Position)) + theme_classic() + labs(title = "Violin plot des poids par poste")
gg2
= ggplot(db) + geom_boxplot(aes(y = Position, x = âge, color = Position)) + theme_classic() + labs(title = "Boxplot des âges par poste")
gg3
= ggplot(db) + geom_violin(aes(y = Position, x = Rating, color = Position)) + theme_classic() + labs(title = "Violin plot des notes par poste")
gg4
grid.arrange(gg1, gg2, gg3, gg4, ncol = 2, nrow = 2)
De manière analogue, et plutôt logiquement, la répartition des poids par poste semble suivre la même forme. Quand aux âges, les différences sont moindres, alors que pour les notes, c’est la réparition qui différe beaucoup, malgré une moyenne relativement similaire entre les postes.
%>% filter(Position == 'F') %>% ggplot() + geom_point(aes(x = âge, y = Goals)) db
Sur le graphe ci-dessus, on remarque de manière assez surprenante que le plus grand nombre de but est marqué par des joueurs d’environ 30 ans, avec une distribution très symétrique autour de cet âge. Il y a quasiment autant de buts marqués par des joueurs de plus de 40 ans que par des joueurs de moins de 25, ce qui est très surprenant, et mériterait probablement d’être creusé plus tard.
Maintenant qu’une première prise en main a permis de visualiser quelques informations brutes, il est temps à présent de plonger dans une analyse en composante principale plus poussée. Pour se faire, il est d’abord nécessaire d’extraire seulement les variables numériques dans une sous base db_pca, et de bien penser à centrer et réduire les données qui ont des ordres de grandeurs très différents (à l’aide de l’argument scale.unit = TRUE, dont c’est la valeur par défaut). Pour le reste la fonction PCA() du package FactoMineR implémente d’elle même une ACP très complète, dont il est ensuite nécessaire d’étudier précisement les résultats.
= db %>% select(âge, CM, KG, Mins, Goals, Assists, Yel, Red, SpG, `PS%`, AerialsWon, MotM, Rating)
db_pca
= PCA(db_pca, scale.unit = T) res_pca
Dans un premier temps, il est nécessaire d’interpréter le cercle des corrélations. Les ‘petites’ fléches qui sont loins du cercle correspondent au variables (âge, Red, PS%) très mal représentées sur ces deux premiers axes factorielles et peuvent donc être mises de côtés. Pour ce qui est de la première composante principale, on voit que les variables, Mins, Ratin, MotM, Goals, SpG, Assists sont toutes positivement bien corrélées avec elles. Ces variables semblent nous indiquer que cette axe indique probablement une notion de ‘bonne performance’ et les individus sur la droite du graphique auront tendance à avoir de grosses valeurs dans toutes ces catégories, et sont donc probablement les meilleurs footballeurs. A contrario, ceux placés à droite seront les individus les moins performants. Pour ce qui est du deuxième axe, il est extrémement clair qu’il nous renseigne sur la morphologie du footballeur, avec des variables de taille (CM) et de poids (KG) qui lui sont très corrélés. Les joueurs grands et massifs se trouveront sur le haut du graphs et les plus petits et/ou légers se trouveront vers le bas.
Nous pouvons ainsi passer au deuxième graphe qui nous montre la projection des individus dans le premier plan factoriel composé des deux composantes principales les plus informatives. Grâce aux informations déduites précédemment, il est possible de définir 4 grands ‘cadrans’ dans notre graph, où on aurait (de manière caricaturale bien sûr) les footballeurs costauds et talentueux en haut à droite, talentueux et plus petit/léger en bas à droite. Quand aux grands moins performants, ils se trouvent en haut à gauche, et en bas à gauche pour les joueurs petits et peu performants. Il est toujours intéressant de vérifier ces affirmations en procédant à des vérifications de par notre connaissance qui dépendent du contexte et de nos connaissances. Par exemple, il y a en bas à droite quelques points très éloignés des autres dans le cadrant des ‘petits/talentueux’. Un suiveur, même lointain, du football européen aura tôt fait de penser à Lionel Messi, et il s’agit en effet de lui, pour différente années de performances. Une simple ACP nous aura donné en quelques secondes une illustration extrémement claire de ce que tous les spécialistes du football s’accorde à dire: ce joueur sort complétement de l’ordinaire! Et quelques calculs d’algèbre linéaire, sans la moindre notion de contexte sportif réussissent à le mettre en évidence. Impressionnant, et prometteur pour la suite.
Pour choisir le nombre d’axes à retenir et les analyser plus en détail, il sera nécessaire de bien regarder (au moins) le summary des résultats
summary(res_pca)
##
## Call:
## PCA(X = db_pca, scale.unit = T)
##
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6 Dim.7
## Variance 3.914 2.222 1.401 1.028 0.913 0.814 0.667
## % of var. 30.107 17.095 10.779 7.909 7.021 6.258 5.132
## Cumulative % of var. 30.107 47.202 57.981 65.890 72.911 79.169 84.301
## Dim.8 Dim.9 Dim.10 Dim.11 Dim.12 Dim.13
## Variance 0.546 0.438 0.349 0.289 0.217 0.202
## % of var. 4.202 3.369 2.683 2.221 1.670 1.554
## Cumulative % of var. 88.503 91.873 94.555 96.776 98.446 100.000
##
## Individuals (the 10 first)
## Dist Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3
## 1 | 3.601 | -1.613 0.003 0.201 | -0.012 0.000 0.000 | -0.550
## 2 | 4.540 | 3.273 0.013 0.520 | 0.951 0.002 0.044 | 0.277
## 3 | 3.745 | 0.900 0.001 0.058 | -3.010 0.019 0.646 | 0.443
## 4 | 7.522 | 4.946 0.029 0.432 | -4.472 0.042 0.353 | -1.371
## 5 | 3.776 | 0.309 0.000 0.007 | -0.550 0.001 0.021 | -1.108
## 6 | 7.082 | 5.374 0.034 0.576 | -2.052 0.009 0.084 | -2.894
## 7 | 4.188 | 1.009 0.001 0.058 | -3.108 0.020 0.551 | -0.981
## 8 | 3.011 | -0.752 0.001 0.062 | 0.994 0.002 0.109 | -1.111
## 9 | 5.885 | 4.158 0.020 0.499 | -3.290 0.023 0.313 | -0.801
## 10 | 3.561 | 0.367 0.000 0.011 | -0.482 0.000 0.018 | -0.226
## ctr cos2
## 1 0.001 0.023 |
## 2 0.000 0.004 |
## 3 0.001 0.014 |
## 4 0.006 0.033 |
## 5 0.004 0.086 |
## 6 0.028 0.167 |
## 7 0.003 0.055 |
## 8 0.004 0.136 |
## 9 0.002 0.019 |
## 10 0.000 0.004 |
##
## Variables (the 10 first)
## Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr cos2
## âge | 0.158 0.640 0.025 | 0.245 2.705 0.060 | 0.199 2.833 0.040
## CM | -0.028 0.020 0.001 | 0.867 33.830 0.752 | -0.264 4.975 0.070
## KG | 0.018 0.008 0.000 | 0.847 32.318 0.718 | -0.283 5.706 0.080
## Mins | 0.760 14.763 0.578 | 0.197 1.747 0.039 | 0.299 6.396 0.090
## Goals | 0.759 14.714 0.576 | -0.168 1.268 0.028 | -0.427 13.035 0.183
## Assists | 0.717 13.145 0.515 | -0.316 4.507 0.100 | -0.157 1.749 0.025
## Yel | 0.583 8.691 0.340 | 0.149 1.004 0.022 | 0.547 21.325 0.299
## Red | 0.198 1.005 0.039 | 0.184 1.516 0.034 | 0.442 13.916 0.195
## SpG | 0.682 11.893 0.465 | -0.270 3.275 0.073 | -0.387 10.697 0.150
## PS% | 0.165 0.696 0.027 | -0.291 3.807 0.085 | 0.427 12.989 0.182
##
## âge |
## CM |
## KG |
## Mins |
## Goals |
## Assists |
## Yel |
## Red |
## SpG |
## PS% |
Cette commande nous permet de balayer rapidement trois aspects fondamentaux de l’ACP: la variance exprimée par chaque composante principale, les contributions des individus (les 10 premiers), les contributions des variables (les 10 premières). Pour les petits jeux de données, ou si l’on a peu de temps, ce summary peut suffire à un première analyse rapide des données.
Si l’on souhaite avoir une vision plus globale et graphique pour sélectionner le nombre d’axes à retenir, on pourra afficher un figure appelée ‘ébouli des valeurs propres’. Le package factoextra
nous propose une fonction bien pratique effectuer pour cette tâche (l’argument addlabels sert uniquement à afficher les pourcentages explicitement).
fviz_screeplot(res_pca, addlabels = T)
En pratique, le choix du nombre d’axes est relativement arbitraire, bien qu’il existe différents critères objectifs (critère du coude, règle de Kayser, …), en fonction du contexte et surtout du temps disponible pour notre analyse. Ici, on sélectionne 3 axes à analyser, ce qui nous donne déjà environ 58% de variance expliquée.
Pour pouvoir interpréter correctement chaque axe retenu, il est nécessaire d’étudier plus en détail la façon dont ils ont été construits. Pour cela, il peut être intéressant d’étudier la contribution de chaque variable aux composantes principales, ainsi que leur qualité de représentation, avec les commandes ci-dessous.
$var$contrib res_pca
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5
## âge 0.639972121 2.70539508 2.833371 53.504623571 12.820571703
## CM 0.020283700 33.82972898 4.975023 1.251309856 0.070356470
## KG 0.008185462 32.31753359 5.706443 0.020267359 0.401387865
## Mins 14.762798230 1.74691774 6.395595 2.318290548 0.068266488
## Goals 14.713854330 1.26754944 13.034755 0.001207545 0.783013868
## Assists 13.145460851 4.50663921 1.748961 0.910580186 0.001241685
## Yel 8.690630907 1.00436281 21.324697 0.062767948 0.003126891
## Red 1.004906133 1.51587923 13.916214 0.072160617 62.178312439
## SpG 11.892617031 3.27546385 10.696821 0.845926352 0.452739921
## PS% 0.695581268 3.80711645 12.989357 22.122915244 18.597007616
## AerialsWon 3.305620330 12.96375759 1.179799 18.314352346 0.450380062
## MotM 15.471539560 0.05245911 4.014579 0.120038505 0.397455548
## Rating 15.648550077 1.00719690 1.184385 0.455559925 3.776139443
$var$cos2 res_pca
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5
## âge 0.0250480296 0.060124693 0.03970174 5.500841e-01 1.170209e-01
## CM 0.0007938888 0.751831803 0.06971097 1.286479e-02 6.421849e-04
## KG 0.0003203728 0.718224777 0.07995977 2.083699e-04 3.663703e-03
## Mins 0.5778048683 0.038823495 0.08961630 2.383448e-02 6.231084e-04
## Goals 0.5758892407 0.028170015 0.18264549 1.241484e-05 7.147029e-03
## Assists 0.5145034944 0.100155537 0.02450678 9.361727e-03 1.133359e-05
## Yel 0.3401447861 0.022320956 0.29880574 6.453209e-04 2.854098e-05
## Red 0.0393312736 0.033688896 0.19499666 7.418875e-04 5.675381e-01
## SpG 0.4654681254 0.072793900 0.14988591 8.697018e-03 4.132424e-03
## PS% 0.0272245300 0.084609346 0.18200937 2.274470e-01 1.697458e-01
## AerialsWon 0.1293795045 0.288106513 0.01653156 1.882909e-01 4.110884e-03
## MotM 0.6055444732 0.001165851 0.05625306 1.234123e-03 3.627811e-03
## Rating 0.6124725323 0.022383941 0.01659583 4.683638e-03 3.446705e-02
Si l’on préfère avoir ces informations sous la forme d’un graphique, il sera encore une fois possible de faire appel au package factoextra
:
fviz_contrib(res_pca, choice = 'var', axes = 1)
fviz_contrib(res_pca, choice = 'var', axes = 2)
On retrouve bien sur les deux premiers axes les variables que l’on avait retenu dans notre analyse préalable. Regardons maintenant les nouvelles variables d’influence sur le troisième axe.
fviz_contrib(res_pca, choice = 'var', axes = 3)
Les cartons, le nombre de tirs, de buts, et le pourcentage de passes réussies sont donc les variables les plus influentes sur ce troisième axe et serviront principalement à son interprétatation. En affichant le cercle des corrélations utilisant les 2ème et 3ème composantes principales, on peut remarquer que ce 3ème axe semble opposer les attaquants, qui tirent et marquent beaucoup, aux défenseurs/milieux, qui réussissent beaucoup de passes et prennent beaucoup de cartons.
fviz_pca_var(res_pca, axes = c(2,3))
On pourra constater que cette interprétation est logique sur le graphique ci-dessous en prenant un exemple. En effet, l’individu 293 n’est autre que Marco Verrati, qui est situé dans le cadrant en haut à gauche. D’après notre interprétation, il s’agit d’une position qui correspond à un joueur plutôt petit et maigre, qui réussit beaucoup de passes et prend beaucoup de cartons, ce qui est exactement le profil de Verrati. Nous sommes donc rassurés sur notre interprétation.
fviz_pca_ind(res_pca, axes = c(2,3))
Pour résumer, voici ci-dessous les étapes importantes à mettre en place dans une ACP (cela sera vrai aussi pour l’AFC que l’on voit par la suite):
- Choix du nombre de composantes principales que l’on retient.
- Analyse des composantes principales retenues:
- Contributions/qualités de représentations de chaque variables à l’axe 1/2/3…,
- Sélection des variables importantes pour chaque axe,
- Interprétation de chaque composante principale retenue à l’aide de ces variables.
- Analyse des individus sur les différents plans factoriels.
Analyse Factorielle des Correspondances (AFC)
Lorsque les variables que l’on souhaite analyser ne sont plus quantitatives mais qualitatives, il n’est plus possible d’effectuer une ACP. Une solution possible est d’avoir recours à l’Analyse Factorielle des Correspondances (AFC). Cette méthode, un cas particulier d’ACP, permet d’étudier deux variables qualitatives, en analysant les différentes modalités prises par ces deux variables. Pour cela, il est nécessaire tout d’abord de sélectionner deux variables pouvant être considérées comme qualitatives. Ici on choisira par exemple le poste du joueur et le nombre de carton rouge reçu (qui est certes numérique, mais qui peut être considérée comme qualitative pour l’occasion).
= db %>% select(Red, Position) db_ca
Ensuite, on transforme notre base de données en tableau de contigence
, qui va compter pour chaque modalité, le nombre d’individus correspondants.
= table(db_ca$Red, db_ca$Position)
tab_ca tab_ca
##
## D F GK M
## 0 7348 4957 1539 4636
## 1 1493 458 151 612
## 2 223 33 8 65
## 3 20 3 0 3
## 4 1 0 0 0
## 5 1 0 0 0
On peut déjà remarquer dans ce tableau que les modalités 4 et 5 pour les cartons rouges sont très mal représentées avec un seul individu. En général, il est plus sage de retirer ces modalités de l’analyse car elles biaisent souvent l’AFC comme nous le verrons ci-dessous. Plutôt que de les retirer à la main, la fonction CA
permettant d’effectuer une AFC, propose une argument row.sup permettant d’indiquer des lignes à mettre en ‘supplémentaire’. Ces modalités ne serviront pas à construire les axes, mais seront tout de même projetées sur le plan factoriel pour information.
= CA(tab_ca, row.sup = c(5,6)) res_ca
On peut en effet voir sur ce graph que les modalités 4 et 5 sont en bleus foncés, et donc traitées à part dans l’AFC.
summary(res_ca)
##
## Call:
## CA(X = tab_ca, row.sup = c(5, 6))
##
## The chi square of independence between the two variables is equal to 364.5086 (p-value = 5.047295e-73 ).
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3
## Variance 0.017 0.000 0.000
## % of var. 99.561 0.411 0.028
## Cumulative % of var. 99.561 99.972 100.000
##
## Rows
## Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr
## 0 | 2.236 | 0.051 13.272 1.000 | -0.001 0.569 0.000 | 0.000 0.401
## 1 | 9.555 | -0.275 56.667 0.999 | 0.009 15.421 0.001 | 0.002 15.317
## 2 | 4.509 | -0.543 26.716 0.998 | -0.022 10.326 0.002 | -0.014 61.432
## 3 | 0.616 | -0.683 3.345 0.915 | -0.206 73.684 0.083 | 0.030 22.850
## cos2
## 0 0.000 |
## 1 0.000 |
## 2 0.001 |
## 3 0.002 |
##
## Columns
## Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr
## D | 8.827 | -0.145 52.402 1.000 | -0.002 3.102 0.000 | 0.001 2.341
## F | 5.818 | 0.151 34.384 0.995 | -0.010 39.608 0.005 | 0.000 0.712
## GK | 1.746 | 0.148 10.279 0.991 | 0.012 17.248 0.007 | 0.006 64.593
## M | 0.524 | 0.045 2.935 0.944 | 0.011 40.042 0.053 | -0.002 32.354
## cos2
## D 0.000 |
## F 0.000 |
## GK 0.002 |
## M 0.003 |
##
## Supplementary rows
## Dim.1 cos2 Dim.2 cos2 Dim.3 cos2
## 4 | -1.115 0.906 | -0.271 0.054 | 0.236 0.040 |
## 5 | -1.115 0.906 | -0.271 0.054 | 0.236 0.040 |
Encore une fois, le summary des résultats de l’AFC peuvent nous permettre une première analyse plus fine pour une meilleure interprétation du gaphique.