Analyse descriptive bivariées sous R

Décrivez un lien entre 2 variables catégorielles en visualisant les profils ligne, colonne et marginaux

Décrire un lien entre deux variables qualitatives passe souvent par la construction d'une table de contingence et la visualisation des profils en ligne ou en colonne. Le diagramme en barres empilées constitue alors un choix souvent judicieux pour obtenir un visuel efficace.
Nous allons voir dans cet article comment générer ces diagrammes et comment joindre, pour comparaison, les profils marginaux attendus en cas d'indépendance des 2 variables.

Données de travail

Nous allons travailler avec un dataset regroupant les effectifs d'une société, par sexe et par division. Ce dataset comprend d'autres informations mais nous allons nous concentrer sur ces 2 colonnes uniquement. Notre objectif est de décrire le lien qu'il existe entre le sexe d'un salarié et la division dans laquelle il travaille.
Pour information ce dataset comporte 186 salaries, la variable "sexe" compte 2 modalités (H et F), la variable "division" en compte 9. Enfin le dataset est disponible ici.

Nous allons tout d'abord charger nos données dans un dataframe "df_salaries", puis ne retenir que les colonnes "sexe" et "division" :


df_salaries <- read.table("salaries_par_division.csv", header = TRUE,
                       sep = ";",
                       quote = "\"",
                       fill = TRUE,
                       comment.char = "",
                       encoding="UTF-8")

df_salaries <- df_salaries[,c('division', 'sexe')]
head(df_salaries)
      division sexe
1      acceuil    F
2       ventes    H
3 informatique    H
4 informatique    F
5 informatique    H
6 informatique    H
...

Première solution : la fonction plotct issue du package FactoClass

Le package FactoClass contient en effet une fonction très utile qui répond à notre besoin. Il s'agit de la solution la plus simple et la plus rapide. Cependant nous avons des options relativement limitées en termes de rendu.

Première étape : Transformer notre dataframe en table de contingence


cont_salaries <- table(df_salaries)
cont_salaries
                     sexe
division               F  H
  acceuil              8  8
  comptabilit?        15 10
  exploitation         5 13
  gestion              9 15
  informatique        10 29
  projet               7  7
  ressources humaines  7  5
  secretariat         12  0
  ventes              11 15

Seconde étape : Installer le package FactoClass


install.packages("FactoClass")
library(FactoClass)

Troisième étape : Dresser les profils

La fonction plotct permet, entre autres, de tracer les profils lignes et colonnes. Affichons d'abord les profils en ligne associés a la table de contingence créée précédemment. Ces profils vont donc nous informer sur la répartition des différentes divisions pour chacun des deux sexes.


colors <- c("#00AFBB", "#E7B800")
par(mar = c(5, 10, 2, 2)) 
plotct(cont_salaries, profiles="row", col=colors)

Nous définissons tout d'abord les couleurs associées aux 2 modalités de la variable "sexe", puis initialisons les marges afin que les textes ne débordent pas de l'écran. Enfin nous demandons à plotct de nous dresser les profils en ligne. Voici le résultat :

R analyse bivariee profile marginal contingence table

Nous avons donc, en une seule ligne de code la répartition des sexes par division. La première barre, en haut du graphique, nous donne le profil marginal. En situation d'indépendance des variables sexe et division, toutes les divisions devraient présenter ce profil.

Traçons à présent les profils en colonne :


colors <- c("#00AFBB", "#E7B800", "#42FF33", "#FF3349",
            "#6C3483", "#2874A6", "#45B39D", "#A04000",
            "#212F3D")
par(mar = c(3, 3, 2, 2)) 
plotct(cont_salaries, profiles="col",col=colors)

Le code est le même, à l'exception des couleurs, en nombre plus important puisque la variable division compte 9 modalités. Voici le résultat :

R analyse bivariee profile marginal contingence table

Nous avons, cette fois, la répartition des divisions par sexe. La barre à droite nous donne le profil marginal. En situation d'indépendance des variables sexe et division, les hommes, comme les femmes devraient présenter ce profil.

A noter qu'il est possible, via l'option tables d'obtenir en sortie de la fonction plotct les tables de contingence ainsi que des profils ligne et colonne :


tabmarg <- plotct(cont_salaries, profiles="both", tables=TRUE)
tabmarg
$ctm
                     F   H marR
acceuil              8   8   16
comptabilit?        15  10   25
exploitation         5  13   18
gestion              9  15   24
informatique        10  29   39
projet               7   7   14
ressources humaines  7   5   12
secretariat         12   0   12
ventes              11  15   26
marC                84 102  186

$perR
                        F    H
acceuil              50.0 50.0
comptabilit?         60.0 40.0
exploitation         27.8 72.2
gestion              37.5 62.5
informatique         25.6 74.4
projet               50.0 50.0
ressources humaines  58.3 41.7
secretariat         100.0  0.0
ventes               42.3 57.7
marg                 45.2 54.8

$perC
                       F    H marg
acceuil              9.5  7.8  8.6
comptabilit?        17.9  9.8 13.4
exploitation         6.0 12.7  9.7
gestion             10.7 14.7 12.9
informatique        11.9 28.4 21.0
projet               8.3  6.9  7.5
ressources humaines  8.3  4.9  6.5
secretariat         14.3  0.0  6.5
ventes              13.1 14.7 14.0

Seconde solution : Traçage manuel via ggplot

Ce que nous venons de faire avec plotct, nous pouvons tout à fait le faire manuellement avec la librairie ggplot2. Chargeons tout d'abord la librairie puis définissons un thème. Initialisons enfin les couleurs :


library(ggplot2)
theme_set(
  theme_classic() + 
    theme(legend.position = "right")
)

colors <- c("#00AFBB", "#E7B800", "#42FF33", "#FF3349",
            "#6C3483", "#2874A6", "#45B39D", "#A04000",
            "#212F3D")

Commençons par dresser les profils en ligne :


ggplot(data=df_salaries, aes(x=division)) + 
  geom_bar(position = "fill", aes(y = after_stat(count)/sum(after_stat(count)), fill = sexe), alpha=0.4) +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  ggtitle("Profils en ligne observés") +
  ylab("% de salariés") +
  xlab("") +
  theme(
    plot.title = element_text(size=9, hjust = 0.5, face="bold", color="black"),
    axis.title = element_text(size=8),
    axis.text.x = element_text(angle = 30, hjust=1),
    legend.title = element_blank())
R analyse bivariee profile marginal contingence table

Nous obtenons la même chose que précédemment, cependant, grâce à la puissance de la librairie ggplot2, nous avons la main sur tous les éléments du graphique et pouvons le designer à notre guise. Vous noterez que le profil marginal n'apparait pas ici. Nous allons nous en occuper par la suite.

Avant cela, dressons les profils en colonne :


ggplot(data=df_salaries, aes(x=sexe)) + 
  geom_bar(position = "fill", aes(y = after_stat(count)/sum(after_stat(count)), fill = division), alpha=0.4) +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  ggtitle("Profils en colonne observés") +
  ylab("% de salariés") +
  xlab("") +
  theme(
    plot.title = element_text(size=9, hjust = 0.5, face="bold", color="black"),
    axis.title = element_text(size=8),
    legend.title = element_blank())
R analyse bivariee profile marginal contingence table

Il est intéressant de présenter également les profils marginaux à des fins de comparaison entre les profils observés et les profils attendus en cas d'indépendance des deux variables étudiées. La fonction plotct permet de dresser les profils marginaux sur le graphique même. Nous pouvons néanmoins sans plotct facilement les déterminer. Pour cela nous allons créer une fonction qui va nous permettre de construire le dataframe associé.


buildIndependance <- function (source, key1, key2, pivot){
  df <- expand.grid(unique(source[,c(key1)]), unique(source[,c(key2)]))
  colnames(df) <- c(key1, key2)
  pr <- table(source[[pivot]])/length(source[[pivot]])
  pr <- as.data.frame(pr)
  df <- merge(x = df, y = pr, by.x = pivot, by.y = 'Var1') 
  return(df)
}

La fonction ci-dessus accepte 4 paramètres en entrée :

  • source : le dataframe sur lequel nous travaillons, df_salaries donc,
  • key1 : la première colonne à analyser, sexe en ce qui nous concerne,
  • key2 : la seconde colonne d'analyse, division donc,
  • pivot : une des 2 colonnes précédentes, ceci correspond aux profils ligne ou colonne

Nous créons, dans cette fonction, un dataframe de toutes les combinaisons possibles entre les modalités des 2 variables, puis y spécifions les noms de colonnes d'origine. Suite à cela, nous établissons la table de contingence associée au dataframe d'origine avant d'effectuer une jointure entre nos deux structures de données pour associer à chaque couple la fréquence marginale de la modalité pivot.

Calculons, via cette fonction, les profils en ligne marginaux :


rowMarg <- buildIndependance(df_salaries, 'sexe', 'division', 'sexe')

Puis dressons le graphique associé :


ggplot(data=rowMarg, aes(x=division, y = Freq, fill = sexe)) + 
  geom_bar(stat = "identity", alpha=0.4) +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  ggtitle("Profils en ligne attendus si indépendance") +
  ylab("% de salariés") +
  xlab("") +
  theme(
    plot.title = element_text(size=9, hjust = 0.5, face="bold", color="black"),
    axis.title = element_text(size=8),
    axis.text.x = element_text(angle = 30, hjust=1),
    legend.title = element_blank())
R analyse bivariee profile marginal contingence table

Nous obtenons la même chose que la fonction plotct, à la différence que nous avons le profil marginal pour chacune des modalités de la division.

Faisons de même pour les profils en colonne :


colMarg <- buildIndependance(df_salaries, 'sexe', 'division', 'division')

ggplot(data=colMarg, aes(x=sexe, y = Freq, fill = division)) + 
  geom_bar(stat = "identity", alpha=0.4) +
  scale_color_manual(values = colors) +
  scale_fill_manual(values = colors) +
  ggtitle("Profils en colonne attendus si indépendance") +
  ylab("% de salariés") +
  xlab("") +
  theme(
    plot.title = element_text(size=9, hjust = 0.5, face="bold", color="black"),
    axis.title = element_text(size=8),
    legend.title = element_blank())
R analyse bivariee profile marginal contingence table

Retrouvez dans la rubrique "Nos datasets" toutes les données dont vous aurez besoin pour tester et pratiquer !