Data visualisation des variables catégorielles
Pour faire suite à un premier article concernant la description des variables catégorielles, publié il y a quelques semaines, je vais vous présenter, dans ce billet, quelques visualisations particulièrement adaptées à la représentation graphique de ce type de données. J’en utilise classiquement trois :
Les couleurs peuvent facilement être changées grâce à l’addin
Pour changer l’ordre des modalités, par exemple pour que « Ulcer=oui » apparaisse en premier, on peut utiliser la fonction
Lorsque la variable catégorielle a plus de deux modalités, comme par exemple la variable
Puis le mosaic plot après la modification de l’ordre des modalités ou niveaux (ou encore levels) de la variable catégorielle
Les espaces entres les différentes zones ont été augmentés à l’aide de l’argument
Là aussi on peut réordonner les niveaux de la variable 
Et les pie charts (plot en camembert) me direz vous ?Je n’aime pas les utiliser car lorsqu’il y a plus de 3 ou 4 catégories, ils sont parfois difficiles à lire.
- les mosaic plots
- les bar plots
- et les stacked bar plots.
Melanoma2
que j’ai créé à partir du jeu de données Melanoma
du package MASS
. 1. Les Données
library(MASS) Melanoma$status <- as.factor(Melanoma$status) Melanoma$sex <- as.factor(Melanoma$sex) Melanoma$ulcer <- as.factor(Melanoma$ulcer) Melanoma2 <- Melanoma levels(Melanoma2$status)[c(1,2,3)] <- c("dcd_Melanome", "vivant", "dcd_autres") levels(Melanoma2$sex)[c(1,2)] <- c("F", "M") levels(Melanoma2$ulcer)[c(1,2)] <- c("Non", "Oui") head(Melanoma2) ## time status sex age year thickness ulcer ## 1 10 dcd_autres M 76 1972 6.76 Oui ## 2 30 dcd_autres M 56 1968 0.65 Non ## 3 35 vivant M 41 1977 1.34 Non ## 4 99 dcd_autres F 71 1968 2.90 Non ## 5 185 dcd_Melanome M 52 1965 12.08 Oui ## 6 204 dcd_Melanome M 28 1971 4.84 Oui
2. Les Mosaic plots
Les mosaic plots sont particulièrement adaptés pour représenter les fréquences ou les pourcenatges des combinaisons de 2 variables catégorielles (voir le premier article).Les fréquences sont reportées sur l’axe des Y, alors que l’axe des X comporte les modalités d’une des variables. La seconde variables est représentées par des sous divisions sur l’axe des Y. La somme des fréquences pour chaque modalité de la variable représentée en X vaut 1. Les surfaces des combinaison des deux variables sont proportionnelles à leur fréquence globale. Par exemple ici, le mosaic plot de la combinaison des variables ulcer et sexe :Les mosaic plot peuvent être réalisés très facilement avec le packageggmosaic
.library(ggplot2) library(ggmosaic) ggplot(Melanoma2)+ geom_mosaic(aes(x=product(sex,ulcer), fill=sex))+ ylab("Frequence")+ xlab("ulcer")+ ggtitle("Répartition des données en fonction du sexe\net de la présence ou non d'un ulcer")

Colour Picker
comme expliqué ici.Cela est très utile pour, par exemple, mettre au second plan les données du sexe masculin en employant une couleur grise.ggplot(Melanoma2)+ geom_mosaic(aes(x=product(sex,ulcer), fill=sex))+ ylab("Frequence")+ xlab("Ulcer")+ ggtitle("Répartition des données en fonction du sexe\net de la présence ou non d'un ulcer")+ scale_fill_manual(values=c("#EE00EE", "#636363"))

relevel
, comme ceci:Melanoma2$ulcer <- relevel(Melanoma2$ulcer, ref="Oui") ggplot(Melanoma2)+ geom_mosaic(aes(x=product(sex,ulcer), fill=sex))+ ylab("Frequence")+ xlab("Ulcer")+ ggtitle("Répartition des données en fonction du sexe\net de la présence ou non d'un ulcer")+ scale_fill_manual(values=c("#EE00EE", "#636363"))

status
, on peut utiliser la fonction ordered
pour définir l’ordre de toutes les modalités. D’abord le mosaic plot avec l’ordre par défaut :ggplot(Melanoma2)+ geom_mosaic(aes(x=product(sex,status), fill=sex), offset = 0.05)+ ylab("Frequence")+ xlab("Ulcer")+ ggtitle("Répartition des données en fonction du sexe\net du status")+ scale_fill_manual(values=c("#EE00EE", "#636363"))+ theme(axis.text.x = element_text(angle=30, hjust=1, vjust=1))

status
par l’utilisation de la fonction ordered
:levels(Melanoma2$status) ## [1] "dcd_Melanome" "vivant" "dcd_autres" Melanoma2$status <- ordered(Melanoma2$status, levels=c("vivant", "dcd_autres", "dcd_Melanome")) levels(Melanoma2$status) ## [1] "vivant" "dcd_autres" "dcd_Melanome" ggplot(Melanoma2)+ geom_mosaic(aes(x=product(sex,status), fill=sex), offset = 0.05)+ ylab("Frequence")+ xlab("Ulcer")+ ggtitle("Répartition des données en fonction du sexe\net du status")+ scale_fill_manual(values=c("#EE00EE", "#636363"))+ theme(axis.text.x = element_text(angle=30, hjust=1, vjust=1))

offset
(valeur par défauut fixée à 0.01) de la fonction geom_mosaic
.Pour plus de détail sur le package ggmosaic, consultez [sa vignette].(<https://cran.r-project.org/web/packages/ggmosaic/vignettes/ggmosaic.html>) 3. Les bar plots
Les bar plots ne doivent pas être employés pour représenter des données numériques continues, parce qu’ils ne permettent pas :- de visualiser la distribution des données
- de visualiser leur dispersion
- de visualiser une éventuelle asymétrie des données
- de mettre en évidence la présence de donées extrêmes (outliers)
- d’identifier les nombre de données sur lesquels ils reposent.
ggplot2
. Pour cela, il est nécessaire de disposer d’un tableau de données avec:- une ligne par modalité (ou combinaison de modalités),
- une colonne contenant les pourcentages,
- une colonne contenant les bornes inférieures de l’intervalle de confiance,
- une colonne contenant les bornes supérieures de l’intervalle de confiance,
- une colonne contenant les modalités de la première variable catégorielle,
- une colonne contenant les modalités de la seconde variable catégorielle.
status
, ainsi que leurs intervalles de confiance. J’ai simplement ajouté, dans le tableau final, les variables sex
et status
afin de les utiliser comme axe des X et comme argument decouleur.library(binom) options(digits=2) TC <- with(Melanoma2, table(status, sex,useNA = "ifany")) # affichage des fréquences pour lesquelles on veut calculer un IC prop.table(TC,1) ## sex ## status F M ## vivant 0.68 0.32 ## dcd_autres 0.50 0.50 ## dcd_Melanome 0.49 0.51 # on récupère le nb d'observations pour les femmes pour tous les status nb.F <- as.vector(TC[,1]) # idem pour les hommes nb.M <- as.vector(TC[,2]) # on récupère le nombre total d'observations pour chaque status nbT <- rowSums(TC) # on calcule les IC pour les fréquences de femmes df.F <- binom.confint(nb.F, nbT, conf.level=0.95, methods="prop.test") rownames(df.F) <- paste("F", rownames(TC), sep="__") # on affiche le tableau obtenu pour les femmes df.F ## method x n mean lower upper ## F__vivant prop.test 91 134 0.68 0.59 0.76 ## F__dcd_autres prop.test 7 14 0.50 0.27 0.73 ## F__dcd_Melanome prop.test 28 57 0.49 0.36 0.63 # idem pour les hommes df.M <- binom.confint(nb.M, nbT, conf.level=0.95, methods="prop.test") rownames(df.M) <- paste("M", rownames(TC), sep="__") df.M ## method x n mean lower upper ## M__vivant prop.test 43 134 0.32 0.24 0.41 ## M__dcd_autres prop.test 7 14 0.50 0.27 0.73 ## M__dcd_Melanome prop.test 29 57 0.51 0.37 0.64 # on colle les lignes df<-rbind(df.F, df.M) # on crée les variables sex et status en utilisant les rownames du data.frame df$sex <- substr(rownames(df),1,1) df$status <- substr(rownames(df),4,100) df ## method x n mean lower upper sex status ## F__vivant prop.test 91 134 0.68 0.59 0.76 F vivant ## F__dcd_autres prop.test 7 14 0.50 0.27 0.73 F dcd_autres ## F__dcd_Melanome prop.test 28 57 0.49 0.36 0.63 F dcd_Melanome ## M__vivant prop.test 43 134 0.32 0.24 0.41 M vivant ## M__dcd_autres prop.test 7 14 0.50 0.27 0.73 M dcd_autres ## M__dcd_Melanome prop.test 29 57 0.51 0.37 0.64 M dcd_Melanome ## plot ggplot(df, aes(x=status,y=mean*100, fill=sex))+ geom_bar(position=position_dodge(), stat="identity") + geom_errorbar(aes(ymin=lower*100, ymax=upper*100),width=.2,position=position_dodge(.9))+ scale_y_continuous(limits=c(0,100))+ ylab("Pourcentage")+ theme_classic()

status
pour, par exemple, afficher la modalité vivant
en premier, et modifier les couleurs.df$status <- ordered(df$status, levels=c("vivant", "dcd_autres", "dcd_Melanome")) ggplot(df, aes(x=status,y=mean*100, fill=sex))+ geom_bar(position=position_dodge(), stat="identity") + geom_errorbar(aes(ymin=lower*100, ymax=upper*100),width=.2, position=position_dodge(.9))+ ylab("Pourcentage")+ scale_y_continuous(limits=c(0,100))+ scale_fill_manual(values=c("#32CD32", "#4876FF"))+ theme_classic()

4. Les Stacked bar plot
Il existe un autre type de bar plot qui peut être utilisé pour représenter des fréquences ou des pourcentage : le « proportional stacked bar plot ». Ca ressemble assez au mosaic plot, sauf que les barres associées aux modalités d’une des variables catégorielles ont toutes la même largeur, elles ne sont pas proportionnelles à leurs fréquences globales. Ci dessous un exemple pour visualiser les pourcentages des différentes modalités de la variablestatus
(vivant, dcd_autres,
dcd_Melanome) par sexe.Dans un premier temps, il est nécessaire de créer un tableau de données (data.frame) avec les pourcentages correspondant. Pour chaque sexe, la somme des pourcentages relatifs aux modalités de la variable status
doit être égale à 1. Pour cela , on utilise les fonctions table
, prop.table
décrites dans le premier article sur l’analyse descriptive des variables catégorielles.TC <- table(Melanoma2$status, Melanoma2$sex,useNA = "ifany") df2 <- prop.table(TC,2) df2 <- df2*100 df2 <- round (df2, 2) df2 <- as.data.frame(df2) names(df2) <- c("status", "sex", "p") df2 ## status sex p ## 1 vivant F 72.2 ## 2 dcd_autres F 5.6 ## 3 dcd_Melanome F 22.2 ## 4 vivant M 54.4 ## 5 dcd_autres M 8.9 ## 6 dcd_Melanome M 36.7On peut ensuite réaliser le plot en utilisant la fonction
geom_bar
. L’ordre des modalités est géré par l’argument limits
de la fonction scale_fill_manual
.ggplot(df2, aes(x=sex, y=p, fill=status)) + geom_bar(stat="identity", position="stack", width=0.5) + coord_flip()+ xlab("sexe")+ ylab("pourcentage")+ scale_fill_manual(values=c("#BAB1B1","#87CEFA","#1C86EE"),limits=c("dcd_Melanome", "dcd_autres", "vivant"))+ theme_classic()

5. Pour aller plus loin
Si vous vous intéressez à la visualisation des données, je vous recommande d’aller jeter un coup d’oeil :- au génial site Flowing Data de Nathan Yau,
- ainsi qu’à l’excellent livre Fundamentals of Data vizualisation en accès libre (pour l’instant ?) de Claus O. Wilke.
Très instructif ! Merci Claire !
Sinon je cherche le code à écrire pour visualiser le pourcentage de réponse « oui » par exemple , dans plusieurs variables grâce à un barplot ( circular ou lollipop de préférence)
Bonjour Claire
super article encore! merci beaucoup.
Juste un détail qui m’échappe. Dans la partie sur les barplots : on crée les variables sex et status en utilisant les rownames du data.frame
df$sex <- substr(rownames(df),1,1)
df$status <- substr(rownames(df),4,100)
je n'arrive pas à comprendre d'où viennent 1,1 et 4, 100
Merci encore
Bonjour Nathalie,
Dans la commande substr(rownames(df),1,1), le premier 1 correspond à la première position du motif à récupérer, et le deuxième 1, correspond à la dernière position de ce motif. Ici comme on veut récupérer uniquement la première lettre, c’est 1 et 1.
Dans la command df$status <- substr(rownames(df),4,100), c'est pareil, le 4 correspond à la position de début du découpage, et je pense que 100 est arbitraire pour être sûre d'avoir l'ensemble du motif. J'espère que cela vous aide. Bonne continuation
theme(axis.text.x = element_text(angle=30, hjust=1, vjust=1))
Vous avez ssauvez ma vie avec ça! j, ai cherche comment representer les effectif pour une variable province avec 26 modalités. j, obtenai de barres mais les modalilités de la variables apparaissaient en axis tres serrées . j, ai cherché comment les placer en verticale inclinées. merci
Bonjour Eric,
Ravie de vous avoir sauvé la vie 😉
Bonne continuation
Bonjour Claire,
Super travail. Cela m’a beaucoup aidé.
Cependant lorsque je fais le « Mosaic plot » en reprenant votre script avec un jeu de données presque semblable, mes fréquences ne sortent pas en chiffre.
Il est écrit à la place Oui ,Non au lieu en lieu et place des fréquences des chiffres.
Merci pour votre aide.
Cordialement.
Amadou
Bonjour Amadou,
Difficile de vous répondre sans avoir les données. Néanmoins, vous pouvez vérifier que la variable est bien de type factor et pas de type character (cela peut avoir un impact sur certaines fonctions).
Par ailleurs, je vosu recommande aussi d’employer la fonction ggbivariate du package GGally, vosu trouverez un exemple dans cet article : https://delladata.fr/matrice-plots-ggpairs-ggally/
Bonne continuation