Découverte :
L'analyse en composantes principales (avec R)

L'ACP, ou Analyse en Composantes Principales, est une méthode d'exploration de données qui consiste à réduire la dimensionnalité du problème pour en extraire l'essentiel. Par une projection dans un espace plus petit, on réduit le nombre de variables, et si on réduit suffisamment on peut en faire un outil de diagnostic graphique. Comme c'est une projection, il est important de comprendre qu'on perd de l'information dans le processus, mais cela permet d'interpréter plus facilement les données.

Table des matières :

La méthode

En pratique, on part d'un tableau avec N lignes représentant les individus mesurés - par exemple 1000 souris - et P colonnes représentant les variables mesurées - par exemple la taille, le poids, l'âge etc. des souris. L'idée, c'est qu'il est facile de représenter sur un graphique une situation à deux variables : la taille sur l'axe des x, le poids sur l'axe des y, un point par souris. On pourrait imaginer ajouter un 3ème axe pour l'âge et visualiser les points dans un "cube" en 3D. Mais à partir de 4 variables, la visualisation devient impossible. Pour réduire la dimension, on va essayer de ne garder que l'essentiel. L'ACP va transformer le tableau pour qu'il ne compte plus que deux (nouvelles) colonnes tout en conservant un maximum d'information.

Sans entrer dans les détails, la transformation implique d'abord une rotation des axes de coordonnées : le premier axe suivra la direction la plus "allongée" (imaginez un poisson ; l'axe va de la tête à la queue), le second une direction perpendiculaire (du ventre vers le dos), le troisième perpendiculaire aux deux premiers (l'épaisseur du poisson), etc. Cela sert à maximiser la variabilité des points le long du premier axe, puis la variabilité du reste le long du second, etc. de sorte qu'il n'y ait presque plus de variation le long des axes suivants. Ces nouveaux axes s'appellent composantes principales ; ce sont P vecteurs de taille P. Mathématiquement, ce sont les vecteurs propres de la matrice de covariance de notre table, et on fait un changement de base.

poisson_orig_axes2

Axes du repère d'origine (image d'origine : wikimedia.org)

poisson_pca_axes2

Axes de l'ACP (composantes principales)

 

Ensuite on fait une sélection des composantes : plus on en garde, plus complètement on peut recomposer l'objet (si on n'a gardé que les deux premières composantes du poisson, on ne peut reconstruire qu'un poisson tout plat).

L'important dans tout ca, c'est que si les deux premières composantes cumulent une grande portion de la variabilité totale, on peut ignorer les autres et les opposer dans un graphique.

Un exemple avec R

Ici nous partirons du jeu de données "iris" déjà inclus dans la plupart des distributions de R. La table ressemble à ça :

Il y a 150 individus et 4 dimensions/variables. Les 150 sont groupés en 3 espèces setosa, versicolor et virginica. Ce qu'on voudrait savoir, c'est s'il y a une différence importante entre les espèces, et s'il y en a une, quelles sont les variables qui contribuent le plus à expliquer cette différence.

Il y a deux commandes à choix pour faire l'ACP en R (j'expliquerai plus tard pourquoi) : prcomp et princomp. Ici je vais utiliser prcomp ; avec princomp le résultat est presque le même, et l'utilisation est identique aux noms des attributs près.

Les composantes principales (PCx, pour "Principal Component") sont les colonnes de pca$rotation :

On voit par exemple que l'axe "PC1" est une combinaison de 0.86 x Petal.Length, 0.36 x de Sepal.Length et Petal.Width, et -0.08 x Sepal.Width - c'est-à-dire que la direction de la PC1 est à peu près alignée avec celle de Petal.Length et quasi perpendiculaire à celle de Sepal.Width.  On appelle aussi ces nombres "loadings".

pca$sdev donne la fraction d'information (sdev="standard deviation") contenue dans chacune des composantes :

Ainsi les deux premières composantes à elles seules contiennent 97.77% de l'information, il est donc raisonnable de garder seulement deux variables en ne perdant que 2.33% d'info, ou même une seule (ce que je ferais en pratique, mais ici on en gardera deux pour plus de généralité). On peut aussi rendre compte de ces proportions avec un bar plot des variances :

sdev_iris

Les variances des composantes principales.

 

Je ne vous cache pas qu'on peut en produire un plus joli soi-même.

Les données transformées par rotation sont dans pca$x ; chaque colonne est la projection des points sur l'une des composantes principales. Ainsi si on garde seulement les deux premières, on a la projection des points dans le plan PC1-PC2 et on peut en faire un graphique qu'on appelle "biplot" :

L'axe horizontal est notre PC1, l'axe vertical la PC2. En coloriant les points selon l'espèce de plante, on voit que la PC1 les distingue presque parfaitement :

pca_iris

ACP sur les données "iris"

 

En fait on a vu que la composante 2 n'est pas très utile, et on pourrait très bien choisir de réduire encore la dimension et séparer nos points selon un seul axe :

 

pca_1d_iris

Projection sur la première composante principale uniquement.

 

L'interprétation ensuite est la suivante : d'abord l'espèce setosa (à gauche) est nettement plus reconnaissable que les deux autres entre elles. Ensuite, comme c'est la composante 1 qui sépare les espèces, on regarde de quoi elle est faite. On avait vu qu'elle était composée principalement de Petal.Length ; on en déduit que c'est principalement à la longueur des pétales qu'on reconnaît les espèces. A vrai dire l'interprétation est souvent difficile, et on se contente alors de remarquer que les groupes sont bien différenciés/groupés comme on l'attend.

Il existe aussi une commande R qui fait le biplot toute seule mais... chacun ses goûts. Les flèches qui apparaissent sur le graphique sont les anciens axes de coordonnées (il y a aura donc P flèches - et on ne peut pas en réduire le nombre, ce qui peut devenir très lourd). Il est aussi centré en zéro et réduit (ce n'est pas important pour l'interprétation).

biplot_iris

Biplot des données iris

Autres applications

On peut se servir de l'ACP par exemple en RNA-seq pour regarder si l'expression globale des gènes est très différente d'un groupe de patients à un autre, ou si les réplicats de l'expérience sont suffisamment semblables - dans le cas contraire ça permet d'éliminer les mauvais échantillons et rendre l'analyse plus robuste. On considère alors ces fameuses tables avec un gène par ligne et une colonne par échantillon, indiquant dans chaque case l'expression d'un gène dans un échantillon particulier.

De façon similaire, on peut mesurer la présence ou l'absence de chaque variation du génome (SNP) de 3000 Européens, et comparer le graphe de l'ACP à la carte de la région, c'est plutôt spectaculaire. C'est aussi un bon exemple de cas où l'interprétation découle directement de la disposition des points et pas du contenu des composantes principales :

genes_in_europe

Biplot d'une ACP sur les différences génétiques en Europe (J. Novembre et al., Nature 2008).

 

Dans des contextes différents, on peut l'appliquer pour la compression d'images, la reconnaissance de mouvements, etc.

Finalement, c'est aussi un moyen de trouver la "meilleure" droite passant par un nuage de points, un peu comme on le fait en régression linéaire, avec l'avantage que le résultat est le même si on échange les axes (ce n'est pas le cas de la régression !). Cette droite passe par le centre du nuage dans la direction du vecteur PC1.

bestline

En rouge : la première composante principale. En bleu : les droites de régression X~Y et Y~X.

 

En bonus, le code pour ce dernier graphique :

Prcomp et princomp

La différence entre ces deux commandes R se trouve dans la méthode mathématique utilisée. La décomposition en composantes principales peut se faire soit par SVD (Décomposition en Valeurs Singulières), soit par recherche des vecteurs propres de la matrice de covariance. Ainsi, on remarque que prcomp (SVD) est plus rapide, et même que si on essaye avec la matrice transposée (voir plus bas), princomp va se plaindre car il n'existe pas suffisamment de vecteurs propres :

alors que pour prcomp tout va très bien :

De plus, le calcul de la SVD est plus stable numériquement. Les noms des attributs sont aussi différents. Voici la correspondance si on y tient :

prcomp -> princomp
pca$x -> pca$scores
pca$rotation -> pca$loadings[,1:4]
pca$sdev -> pca$sdev

Pour aller plus loin

- On peut aussi toujours s'intéresser au problème inverse en transposant la table des données. Par exemple, si on a une table avec une ligne par gène et une colonne par condition expérimentale, l'ACP telle que nous l'avons présentée ressortira un graphique avec un point par gène, et on espère voir des "clusters" de gènes en fonction des échantillons. Si on transpose la table pour avoir une ligne par condition et une colonne par gène, on obtiendra un graphique avec un point par condition, et on espère voir les réplicats ensemble et les malades bien séparés des contrôles.

- Lorsque les variables sont, comme dans l'exemple "iris", du même type (des longueurs, en cm), tout va bien. Mais si on commence à mélanger des tonnes et des microns, alors les échelles seront différentes et l'ACP sera biaisée en faveur des nombres les plus grands. Pour y remédier, on peut choisir de normaliser les variables avec l'option "scale=TRUE", ce qui divisera chaque colonne par sa variance. Si cette normalisation s'avère trop forte (c'est le cas avec les expressions de gènes), on peut simplement appliquer un logarithme.

- La théorie part du principe que les variables initiales sont indépendantes (axes orthogonaux). En pratique on ignore joyeusement cette contrainte, comme par exemple dans le cas de l'expression des gènes. Un inconvénient, c'est que les composantes principales contiennent un mélange d'un peu toutes les variables à la fois, rendant l'interprétation difficile. Il existe une adaptation de l'ACP pour variables corrélées qu'on appelle "ACP éparse" ("sparse PCA"), exploitant la technique du lasso en interprétant l'ACP comme un problème de régression. Alors un grand nombre de coefficients des composantes principales deviennent nuls et on peut plus facilement extraire les variables significatives. Pour plus de détails, voir H. Zou, T. Hastie, R. Tibshirani, "Sparse principal component analysis", 2004. Les auteurs ont implémenté la méthode dans le package R elasticnet.

- Il existe des packages R comprenant des fonctions pour une étude plus poussée de l'ACP, d'ailleurs développés par des Français : FactomineR, Ade4 and amap. Je ne les ai pas testés, mais je vous invite à regarder par exemple ce lien.

 

Merci à HautbitMaxi_Zu et Estel pour leur relecture.

  • À propos de
  • Bioinformaticien @ CHUV / UNIL
    Diplômé EPFL en mathématiques appliquées.
    Développement software, analyse de données génomiques.

41 commentaires sur “L'analyse en composantes principales (avec R)

  1. Super Article!

    J\'ai adoré L\'image du poisson. C\'est vraiment clair comme explication et ça donne une bonne intuition de la projection.

    Ciao.

    • Merci ! J\'ai pas trouvé de poisson en 4D sur le web malheureusement, mais je compte sur l\'imagination du lecteur pour étendre l\'exemple aux dimensions supérieures.

  2. Félicitations ! Très bon billet.

  3. J\'adore! ça parait un peu bête mais quelles sont les avantages d\'un tableur par rapport à R?

    • Le formatage des documents. R sert a faire des analyses sophistiquees et des figures que le tableur ne connait pas, mais pas des jolies tables avec des bordures colorees et des enluminures.

  4. Bonjour Pour quoi ne pas avoir citer la commande PCA(matrice)en plus des commandes prcomp et princomp. la commande PCA possède elle des inconvénients qui la rende inutile?

    • Bonjour. Chez moi (R version 3.1.2),

      > PCA
      Erreur : objet \'PCA\' introuvable
      > PCA(iris[,1:4])
      Erreur : impossible de trouver la fonction \"PCA\"

      Donc la commande \"PCA\" doit venir d\'un package externe. On peut savoir d\'ou elle vient en entrant son som dans la console, comme prcomp qui vient de :

      > prcomp
      function (x, ...)
      UseMethod(\"prcomp\")

      • hmm les \"\" sont interpretees comme des balises html... mais je voulais dire \"vient de stats\", et si on tape \"prcomp\", ca affiche aussi
        bytecode: 0x7f96f56c52e8
        environment: namespace:stats

    • La commande PCA fait partie du package \"FactoMineR\". Elle est très pratique car très complète (calcule les % d\'explication des différentes composantes et superposition des axes des descripteurs pour mieux comprendre la séparation).

  5. Merci pour ce post, très informatif. Serait il possible de nous expliquer aussi simplement la différence entre ACP et l\'analyse en coordonnées principales, implementée en R par cmdscale() ?
    Merci d\'avance.

    • L\'analyse en coordonnees principales calcule les vecteurs propres d\'une matrice de ressemblance, alors que l\'ACP utilise la matrice de covariance (/correlation). Une matrice de ressemblance contient toutes les distances (euclidiennes en principe) entre paires d\'elements.
      L\'ACoP est donc une technique de projection similaire mais dans un contexte ou la notion de distance entre les variables a plus de sens que leur covariance.
      Il existe encore une variante appelee MDS (\"multi-dimensional\" scaling).

      • Bonjour,
        Pourriez-vous expliquer la différence entre une ACP et une MDS? Ainsi qu\'entre une MDS métrique et non-métrique?
        Merci d\'avance pour votre réponse.

        • Le MDS cherche aussi a projeter les points dans un espace de moindre dimension, mais en essayant de conserver au maximum les distances entre les points, alors que la contrainte de la PCA est de minimiser la variance le long de chaque axe.

          En fait la PCoA est la variante \"classique\" de MDS. Les differents MDS se distinguent par la facon de definir la matrice de dissimilarites (p.ex. distances entre les points pour la PCoA). Le MDS est non-metrique si on opere une transformation lineaire des entrees de la matrice de dissimilarites. Je n\'en sais pas plus malheureusement.

  6. Merci très bon article

  7. Bonjour,

    J\'aurais voulu savoir pour le premier exemple, qu\'est-ce qu\'on peut faire avec une seule composante principale ? En termes de représentation graphique et/ou amélioration du modèle si nécessaire ?
    Je me trouve dans un cas similaire et peine à interpréter un tel résultat...
    J\'espère que vous pourrez m\'aider !
    Merci

    • D\'abord ca peut servir a classifier les points, si le long de l\'axe de la CP on voit des groupe des points, plus particulierement un groupe avant le 0 et un groupe apres. Dans l\'exemple c\'est encore plus facile, car on voit tout de suite en ajoutant des couleurs que la CP separe bien les trois groupes de plantes.

      On peut essayer d\'expliquer la difference entre les membres des differents groupes par les variables qui construisent la CP. Si par exemple le vecteur de la CP s\'ecrit (0,0,-0.02,18,0,0), on va dire que c\'est principalement la variable 4 qui est determinante pour classifier les points (mais en principe c\'est une combinaison de plusieurs ; il faut ordonner les composantes de la CP pour mieux les voir. S\'il y en a trop on ne peux rien en faire).

  8. Bonjour,

    J\'aimerais savoir quel package vous avez utilisé pour faire l\'ACP.

    Merci d\'avance

    • Il n\'y a pas besoin de package. Essayez juste les commandes indiquees dans R.

      • Merci beaucoup!

        J\'aimerai aussi savoir s\'il existe d\'autres commandes comme celles là pour effectuer l\'Analyse Factorielle des Correspondances et l\'Analyse des Correspondances Multiples et la Classification?

        • R est fait pour ca, donc oui. Il existe de nombreux livres et tutoriels en ligne. La litterature - comme la doc de R d\'ailleurs - est souvent en anglais par contre, par exemple Classification s\'appelle Clustering.

          • Merci beaucoup!

            C\'est noté.

  9. Super Article!

    Merci pour ce post, très informatif!

  10. Bonjour, je ne comprend pas très bien comment se font les couleurs sur un graphique R. J\'ai bien compris votre exemple en colorant les points associés aux différentes types de plantes, mais si j\'essaye avec cette ligne de code par exemple : plot(pca$x[,1:2],col=iris[,3]), j\'obtiens un graphique avec 5 couleurs différentes, et la je ne comprend plus très bien car ma colonne 3 dans \"iris\" est une succession de valeurs numériques bien distinctes, et non plus 3 chaines de caractères différentes comme dans la colonne 5. Pourriez-vous m\'expliquer si ça ne vous dérange pas ? Merci d\'avance de votre réponse.

    • Oui, c\'est iris[,5]. Si on tape \"iris\" on voit pourquoi.

      • Excusez moi mais je n\'ai toujours pas compris pour mon exemple avec iris[,3] (exemple que j\'ai pris au hasard). Pour iris[,5], on a 3 chaines de caractère différentes, donc je comprend que R fait un graphique avec 3 couleurs différentes pour les distinguer.
        Je voulais aussi vous demander à quoi correspondent les échelles sur le graphique représentant PC2=f(PC1) (Echelle variant de -3 à 4 pour la PC1 et de -1 à 1 pour la PC2)
        Cordialement

        • R s\'attend à un facteur pour les colonnes, donc il faut passer col=as.factor(iris[,3]). C\'est un très bon exemple de pourquoi R est un très mauvais langage (fait n\'importe quoi quand on lui passe un truc faux, au lieu de générer une erreur).
          Pour les échelles, si par exemple PC1 = (0,3,1), alors 1 unité selon cet axe vaut 0*x1 + 3*x2 + 1*x3, où x1, x2, x3 sont les variables d\'origine.

          • Merci de votre réponse.
            Juste une précision, dans notre exemple, on a bien PC1 = (0.36,-0.08,0.86,0.36) si j\'ai bien compris ?

  11. bonjour j\'ai effectué une ACP avec la fonction PCA de FactoMineR et je veux savoir quelle est la fonction analogue a $rotation dans ce package

  12. Bonjour,
    Je voulais juste faire une remarque si vous permettez.
    Vous dites que les colonnes de pca$x sont la projection des points sur l\'une des composantes principales. C\'est pas plutot sur les axes principaux (les vecteurs propres)?
    La projection sur les composantes principales est faisable pour les variables initiales, qui sont de meme nature (dimension) que les CPs, c\'est le role du cercle des corrélations.

    cordialement

    • C\'est la même chose. Les composantes principales sont les axes, après rotation, et ce sont des vecteur propres. De plus, après rotation, on a le même nombre de dimensions. C\'est ensuite seulement qu\'on fait une sélection (si on veut). Le cercle des corrélations est la projection des axes originaux sur les nouveaux axes - plutôt que de projeter les points.

  13. Bonjour,

    J\'aurai une question sur les correspondances MDS / ACP, (j\'ai fouillé à droite à gauche mais je n\'ai pas trouvée de réponses claires). Le MDS ce fait pour moi à partir d\'une matrices de distances, de ce fait une matrice carrée. Je me demande comment créer une matrices de distances entres différentes variables.

    Si qqn à un lien sur ce topic, même dataset de départ mais deux analyses différentes du dataset (mds et acp) je suis preneur.

    Merci pour cet article

    Cordialement,

    Vincent.

  14. Hello

    Super article merci beaucoup !
    Y\'a juste un truc que j\'arrive vraiment pas à comprendre c\'est le paragraphe suivant :

    \"On voit par exemple que l\'axe \"PC1\" est une combinaison de 0.86 x Petal.Length, 0.36 x de Sepal.Length et Petal.Width, et -0.08 x Sepal.Width - c\'est-à-dire que la direction de la PC1 est à peu près alignée avec celle de Petal.Length et quasi perpendiculaire à celle de Sepal.Width.

    Que veux tu dire par direction de PC1 est alignée avec celle de petal.Length ? idem pour perpendiculaire à Sepal.Width

    Merci

    • La PC1 est un vecteur dans un espace de dimension 4 qui est une combinaison linéaire des 4 vecteurs d\'origine. De la même façon qu\'en dim 2 ou 3, les composantes indiquent dans quelle direction pointe ce vecteur - là où les composantes sont grandes.

  15. Bonjour,

    Merci pour cet article.

    J\'aimerai savoir s\'il est possible de récupérer les coordonnées des individus sur l\'axe 1 et d\'obtenir le cercle des corrélations des variables.

    Je vous remercie.

    Cordialement,

    Justine

  16. Bonjour,
    J\'aimerais comment vous avez fait pour remplacer les variables d\'origines par les vecteurs propres.

  17. Bonsoir,
    Je souhaite faire une NMS ou nMDS avec R. Mais je n\'y me retrouve absolument pas.

  18. je souhaite faire une ACP avec mes données.quelles sont les commandes que je peux utiliser et comment faire aussi la visualisation des résultats

    • Bonjour,

      avez-vous lu l\'article? Il décrit précisément la procédure...

  19. Très instructif comme article. Comment faire pou avoir la table des cosinus relative à l\'ACP pour faire des interprétations?( les commandes 🙂 ]

Laisser un commentaire