Corrélation deux à deux, corrélation des paires ou pairwise correlations

    Aujourd’hui, je vous propose un  article sur les corrélations deux à deux ; on les appelle aussi corrélations par paires, ou encore pairwise correlations en anglais. Je commencerai par expliquer pourquoi on peut être amené à calculer ces corrélations par paires, puis je présenterai les principales fonctions que j’utilise pour les représenter.  

Table des matières : 

  • 1.Pourquoi calculer les corrélations deux à deux (corrélation par paires ou pairwise correlations) ?
  • 2.Obtenir la matrice de corrélation : fonction cor()
  • 3. Matrice visuelle avec la fonction pairs()
  • 4 Utilisation du package corrplot
  • 5. Utilisation du package corrr
 

1. Pourquoi calculer  les corrélations deux à deux (corrélation par paires ou pairwise correlations) ?

Classiquement, on s’intéresse à ces corrélations par paires lorsqu’on ajuste un modèle de régression linéaire multiple (ou linéaire généralisé multiple), pour évaluer les effets des variables explicatives sur une variable réponse à expliquer.

En effet, lorsque le modèle de régression multiple comporte plusieurs (au moins deux) variables prédictives fortement liées entre elles de façon linéaire, cela entraîne une instabilité du modèle, et le rend in-interprétable. On parle de multicollinéarité.

Il est donc important de repérer ces variables fortement liées entre elles de façon linéaire, afin de ne pas les inclure simultanément dans le modèle.

Et pour cela, on va calculer le coefficient de corrélation de Pearson, entre toutes les variables numériques deux à deux. C’est ce qu’on appelle les pairwise correlations (ou corrélation deux à deux).

Remarque : Certains utilisent une valeur seuil du coefficient de corrélation de Pearson à 0.85 pour retirer une des deux variable du modèle.

Au delà de ce problème de multicollinéarité, il peut également être intéressant pour mieux comprendre son jeu de données, d’étudier comment les variables sont liées entre elles. Et notamment de connaître les variables qui évoluent dans le même sens, celles qui évoluent à l’opposé, ou encore celles qui sont totalement indépendantes. Cela peut vraiment être utile, par exemple, pour bien comprendre les résultats d’un modèle de régression multiple.

On s’intéresse aussi à ces corrélations deux à deux (ou par paires) lorsqu’on souhaite construire un modèle prédictif, car de nombreux algorithmes de Machine Learning sont plus performants lorsque les prédicteurs ne sont pas fortement corrélés.

Je vais alors vous présenter les principales fonctions que j’utilise lorsque je veux étudier les corrélations deux à deux. Pour les illustrer, je vais utiliser le jeu de données mtcars qui appartient au package datasets (chargé par défaut) en lui retirant les variables am et vs qui sont des variables catégorielles. Je nomme ce nouveau jeu de données mtcars2 :

library(tidyverse)

mtcars2 <- mtcars %>%
select(-vs, -am)
head(mtcars2)

    ##                    mpg cyl disp  hp drat    wt  qsec gear carb
    ## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46    4    4
    ## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02    4    4
    ## Datsun 710        22.8   4  108  93 3.85 2.320 18.61    4    1
    ## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44    3    1
    ## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02    3    2
    ## Valiant           18.1   6  225 105 2.76 3.460 20.22    3    1
   

2.Obtenir la matrice de corrélation deux à deux : fonction cor()

Une façon toute simple d‘obtenir les coefficients de corrélation de Pearson pour toutes les paires de variables, est d’utiliser la fonction cor() du package stats, chargé par défaut.
cor(mtcars2)

    ##             mpg        cyl       disp         hp        drat         wt
    ## mpg   1.0000000 -0.8521620 -0.8475514 -0.7761684  0.68117191 -0.8676594
    ## cyl  -0.8521620  1.0000000  0.9020329  0.8324475 -0.69993811  0.7824958
    ## disp -0.8475514  0.9020329  1.0000000  0.7909486 -0.71021393  0.8879799
    ## hp   -0.7761684  0.8324475  0.7909486  1.0000000 -0.44875912  0.6587479
    ## drat  0.6811719 -0.6999381 -0.7102139 -0.4487591  1.00000000 -0.7124406
    ## wt   -0.8676594  0.7824958  0.8879799  0.6587479 -0.71244065  1.0000000
    ## qsec  0.4186840 -0.5912421 -0.4336979 -0.7082234  0.09120476 -0.1747159
    ## gear  0.4802848 -0.4926866 -0.5555692 -0.1257043  0.69961013 -0.5832870
    ## carb -0.5509251  0.5269883  0.3949769  0.7498125 -0.09078980  0.4276059
    ##             qsec       gear       carb
    ## mpg   0.41868403  0.4802848 -0.5509251
    ## cyl  -0.59124207 -0.4926866  0.5269883
    ## disp -0.43369788 -0.5555692  0.3949769
    ## hp   -0.70822339 -0.1257043  0.7498125
    ## drat  0.09120476  0.6996101 -0.0907898
    ## wt   -0.17471588 -0.5832870  0.4276059
    ## qsec  1.00000000 -0.2126822 -0.6562492
    ## gear -0.21268223  1.0000000  0.2740728
    ## carb -0.65624923  0.2740728  1.0000000
  Mais comme vous pouvez le voir, la matrice de corrélation deux à deux obtenue n’est pas très facile à interpréter.  

3. Matrice visuelle avec la fonction pairs()

Pour avoir une meilleure idée des relations entre les variables, j’aime bien utiliser la fonction pairs() du package graphics (chargé par défaut). Pour que la fonction renvoie une visualisation intéressante, il est nécessaire de copier coller dans la console la fonction panel.cor_simple(). Je l’ai adaptée de la fonction panel.cor disponible ici.

panel.cor_simple <- function(x, y, digits=2, prefix="", cex.cor) 
    {
        usr <- par("usr"); on.exit(par(usr)) 
        par(usr = c(0, 1, 0, 1)) 
        r <- cor(x, y) 
        txt <- format(c(r, 0.123456789), digits=digits)[1] 
        txt <- paste(prefix, txt, sep="") 
        if(missing(cex.cor)) cex <- 0.8/strwidth(txt) 
     
        test <- cor.test(x,y) 
        # borrowed from printCoefmat
        Signif <- symnum(test$p.value, corr = FALSE, na = FALSE, 
                      cutpoints = c(0, 0.001, 0.01, 0.05, 0.1, 1),
                      symbols = c("***", "**", "*", ".", " ")) 
     
        text(0.5, 0.5, txt, cex = cex * abs(r)) 
        text(.8, .8, Signif, cex=cex, col=2) 
    }
  Cette fonction panel.cor_simple() entre dans l’argument upper.pannel de la fonction pairs() :
pairs(mtcars2, lower.panel=panel.smooth, upper.panel=panel.cor_simple)
  pairwise correlation

J’aime bien cette représentation, car dans la partie basse (à gauche), on peut voir la courbe de régression loess (régression de voisinage) entre les deux variables; ça permet d’avoir une idée de la forme de leur relation. Et dans la partie haute (à droite) on retrouve le coefficient de corrélation avec des étoiles pour indiquer la significativité du test d’égalité à zéro du coefficient de corrélation de Pearson.

On peut également obtenir une version plus complète avec le R2 et la p-value du test de l’égalité à zéro du coefficient de corrélation de Pearson, en utilisant la fonction panel.cor() du package “quantable”, en argument de upper.panel.
library(quantable)
pairs(mtcars2, lower.panel=panel.smooth, upper.panel=panel.cor)
  corrélation par paires    

4. Utilisation du package corrplot

Pour obtenir des représentations plus synthétiques et plus visuelles, j’utilise la fonction corrplot(), du package corrplot. Voici quelques visualisations que j’apprécie particulièrement :
library(corrplot)
M <- cor(mtcars2)
corrplot(M, method = "number", type="upper")
  corrélation deux à deux Pour améliorer encore la visualisation, on peut aussi colorier la case en fonction du coefficient de corrélation :
col <- colorRampPalette(c("#BB4444", "#EE9988", "#FFFFFF", "#77AADD", "#4477AA"))

corrplot(M, method="color", col=col(200), 
             type="upper",
             addCoef.col = "black")
  pairwise correlation avec R On peut encore obtenir une permutation des lignes et des colonnes avec l’argument order=”hclust” afin que les variables apparaissent par ensemble selon le sens de leur corrélation.
 corrplot(M, method="color", col=col(200) ,
             type="upper",
             addCoef.col = "black", order="hclust")
  corrélation deux à deux avec R Il est également possible de passer en blanc les cases correspondant à des corrélations non significatives. Pour cela, on utilise dans un premier temps la fonction cor.mtest(), qu’il faut copier coller dans la console.
cor.mtest <- function(mat, ...) {
        mat <- as.matrix(mat)
        n <- ncol(mat)
        p.mat<- matrix(NA, n, n)
        diag(p.mat) <- 0
        for (i in 1:(n - 1)) {
            for (j in (i + 1):n) {
                tmp <- cor.test(mat[, i], mat[, j], ...)
                p.mat[i, j] <- p.mat[j, i] <- tmp$p.value
            }
        }
      colnames(p.mat) <- rownames(p.mat) <- colnames(mat)
      p.mat
    }
    Appliquée sur le jeu de données, cette fonction produit en sortie, non plus une matrice de corrélation deux à deux, mais une matrice de p-values de tests d’égalité à 0 des coefficients de corrélations de Pearson :
 p.mat <- cor.mtest(mtcars2)

    p.mat

    ##               mpg          cyl         disp           hp         drat
    ## mpg  0.000000e+00 6.112687e-10 9.380327e-10 1.787835e-07 1.776240e-05
    ## cyl  6.112687e-10 0.000000e+00 1.802838e-12 3.477861e-09 8.244636e-06
    ## disp 9.380327e-10 1.802838e-12 0.000000e+00 7.142679e-08 5.282022e-06
    ## hp   1.787835e-07 3.477861e-09 7.142679e-08 0.000000e+00 9.988772e-03
    ## drat 1.776240e-05 8.244636e-06 5.282022e-06 9.988772e-03 0.000000e+00
    ## wt   1.293959e-10 1.217567e-07 1.222320e-11 4.145827e-05 4.784260e-06
    ## qsec 1.708199e-02 3.660533e-04 1.314404e-02 5.766253e-06 6.195826e-01
    ## gear 5.400948e-03 4.173297e-03 9.635921e-04 4.930119e-01 8.360110e-06
    ## carb 1.084446e-03 1.942340e-03 2.526789e-02 7.827810e-07 6.211834e-01
    ##                wt         qsec         gear         carb
    ## mpg  1.293959e-10 1.708199e-02 5.400948e-03 1.084446e-03
    ## cyl  1.217567e-07 3.660533e-04 4.173297e-03 1.942340e-03
    ## disp 1.222320e-11 1.314404e-02 9.635921e-04 2.526789e-02
    ## hp   4.145827e-05 5.766253e-06 4.930119e-01 7.827810e-07
    ## drat 4.784260e-06 6.195826e-01 8.360110e-06 6.211834e-01
    ## wt   0.000000e+00 3.388683e-01 4.586601e-04 1.463861e-02
    ## qsec 3.388683e-01 0.000000e+00 2.425344e-01 4.536949e-05
    ## gear 4.586601e-04 2.425344e-01 0.000000e+00 1.290291e-01
    ## carb 1.463861e-02 4.536949e-05 1.290291e-01 0.000000e+00
  Cette matrice est ensuite utilisée en argument de p.mat. Le seuil de significativité peut être modifié.
corrplot(M, method="color", col=col(200),  
             type="upper", order="hclust", 
             addCoef.col = "black", # Ajout du coefficient de corrélation
             tl.col="black", tl.srt=45, #Rotation des etiquettes de textes
             # Combiner avec le niveau de significativité
             p.mat = p.mat, sig.level = 0.05, insig = "blank", 
             # Cacher les coefficients de corrélation sur la diagonale
             diag=FALSE 
             )
  pairwise correlation avec R Vous trouverez d’autres exemples de l’utilisation du package corrplot dans la vignette, ainsi que sur ce post.  

5. Utilisation du package corrr

Un autre package est particulièrement intéressant pour analyser les corrélations deux à deux, il s’agit du package corrr. Ce package est compatible avec le tidyverse.
library(corrr)
library(tidyverse)
  Par exemple, on peut rapidement obtenir la matrice des corrélations deux à deux, avec un format que je trouve très facile à lire.
   M <- mtcars2 %>%
        correlate() %>%
        rearrange() %>%
        shave(upper=TRUE)
  La fonction rearrange(), permet comme tout à l’heure avec la fonction corrplot de réarranger la matrice pour obtenir des groupes de variables fortement corrélées. Les réarrangements ne sont pas identiques, au moins ici avec ce jeu de données.
M

    ## # A tibble: 9 x 10
    ##   rowname     drat    gear      wt    disp     mpg     cyl      hp    carb
    ##   <chr>      <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
    ## 1 drat     NA       NA      NA      NA      NA      NA      NA      NA    
    ## 2 gear      0.700   NA      NA      NA      NA      NA      NA      NA    
    ## 3 wt       -0.712   -0.583  NA      NA      NA      NA      NA      NA    
    ## 4 disp     -0.710   -0.556   0.888  NA      NA      NA      NA      NA    
    ## 5 mpg       0.681    0.480  -0.868  -0.848  NA      NA      NA      NA    
    ## 6 cyl      -0.700   -0.493   0.782   0.902  -0.852  NA      NA      NA    
    ## 7 hp       -0.449   -0.126   0.659   0.791  -0.776   0.832  NA      NA    
    ## 8 carb     -0.0908   0.274   0.428   0.395  -0.551   0.527   0.750  NA    
    ## 9 qsec      0.0912  -0.213  -0.175  -0.434   0.419  -0.591  -0.708  -0.656
    ## # ... with 1 more variable: qsec <dbl>
  Si on le souhaite, on peut facilement obtenir la matrice de corrélation de Spearman, ou de Kendall, à l’aide de l’argument méthod :
s <- mtcars2 %>%
        correlate(method="spearman") %>%
        rearrange() %>%
        shave(upper=TRUE)

    Ms

    ## # A tibble: 9 x 10
    ##   rowname     drat    gear      wt    disp     mpg     cyl      hp    carb
    ##   <chr>      <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
    ## 1 drat     NA       NA      NA      NA      NA      NA      NA      NA    
    ## 2 gear      0.745   NA      NA      NA      NA      NA      NA      NA    
    ## 3 wt       -0.750   -0.676  NA      NA      NA      NA      NA      NA    
    ## 4 disp     -0.684   -0.594   0.898  NA      NA      NA      NA      NA    
    ## 5 mpg       0.651    0.543  -0.886  -0.909  NA      NA      NA      NA    
    ## 6 cyl      -0.679   -0.564   0.858   0.928  -0.911  NA      NA      NA    
    ## 7 hp       -0.520   -0.331   0.775   0.851  -0.895   0.902  NA      NA    
    ## 8 carb     -0.125    0.115   0.500   0.540  -0.657   0.580   0.733  NA    
    ## 9 qsec      0.0919  -0.148  -0.225  -0.460   0.467  -0.572  -0.667  -0.659
    ## # ... with 1 more variable: qsec <dbl>
    On peut aussi obtenir un format plus concis de cette matrice de corrélation deux à deux, avec la fonction fashion().
  fashion(M)

    ##   rowname drat gear   wt disp  mpg  cyl   hp carb qsec
    ## 1    drat                                             
    ## 2    gear  .70                                        
    ## 3      wt -.71 -.58                                   
    ## 4    disp -.71 -.56  .89                              
    ## 5     mpg  .68  .48 -.87 -.85                         
    ## 6     cyl -.70 -.49  .78  .90 -.85                    
    ## 7      hp -.45 -.13  .66  .79 -.78  .83               
    ## 8    carb -.09  .27  .43  .39 -.55  .53  .75          
    ## 9    qsec  .09 -.21 -.17 -.43  .42 -.59 -.71 -.66
 

Mais le vrai plus de ce package, c’est la fonction network_plot(), qui permet un autre type de visualisation qui me semble vraiment très intéressante, même si j’ai très peu de recul sur ce type de graph.

mtcars2%>%
correlate() %>%
network_plot(min_cor = .2)
  correlation deux à deux avec R     Et vous, que pensez vous de cette nouvelle représentation ?  

Dans tous les cas, j’espère que ce court post, vous permettra de mieux étudier les corrélations deux à deux (ou par paire ou encore pairwise corrélation) entre vos variables, que cela soit pour identifier d’éventuels problèmes de multicollinéarité, ou simplement pour mieux comprendre vos données.

Si vous utilisez d’autres fonctions, n’hésitez pas à me les indiquer en commentaire.   Si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee 🙏 👉 Cliquez ici pour soutenir le blog Statistiques et Logiciel R  

Retrouvez ici d’autres articles en lien avec celui que vous venez de lire : 

 

4 réponses

  1. Super post Merci!
    comment faire pour gérer une matrice avec des données manquantes ? sans enlever complétement la colonne?
    encore Merci pour votre super site tres tres informatif

  2. Super article !
    Mais un peu comme la question au dessus, j’obtiens beaucoup de NA à la suite de la fonction cor(). Pourtant je n’ai pas de données manquantes dans mes données brutes.
    Une idée pourquoi j’en obtiens alors dans la matrice de corrélations ?

    Merci d’avance !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *