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 :

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 :

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())

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())

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())

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())

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