Continuons notre exploration des graphes permettant d’illustrer une comparaison entre des variables catégorielles. Intéressons-nous aux diagrammes en mosaïque et au graphe de Marimekko (ou Mekko plot). Ceux-ci mobilisent des éléments rectangulaires, les tuiles de la mosaïque, que se combinent dans grand rectangle. Chacune de ses dimensions est attachée à une des variables. Ainsi, on a en abscisses des barres accolées correspondant aux différentes modalités de la première variable et sur les ordonnées empilées les modalités de la seconde. Les séparations entre modalités sont opérées de manière à représenter les effectifs qui les composent. La taille des groupes désignées par l’intersection des variables est ainsi représentée par la surface du petit rectangle qui lui correspond. Cela facilite l’identification des relations entre les variables.

Tout ceci est un peu abstrait… Prenons un exemple d’utilisation de ce type de graphe pour y voir plus clair et profitons-en pour comparer le rendu avec celui des différentes formes de diagramme à bâtons. Mais, avant de nous lancer, chargeons quelques packages utiles pour la suite.

library(tidyverse)
library(patchwork)
library(scales)
library(rvest)
library(ggmosaic)

Notez la présence de deux packages que nous n’avons pas encore utilisé rvest et ggmosaic. Le premier sert à scrapper des informations sur internet. Le second, comme son nom l’indique, permet intégrer un geom_ supplémentaire dans ggplot pour réaliser facilement un diagramme en mosaïque.

Venons-en aux données mobilisées. Utilisons celles proposées par Bickel et al. (1975)1. Dans cet article, les auteurs s’intéressent au biais de sélection en fonction du sexe affectant les candidats à l’admission à l’université de Berkeley en 1973. Ils montrent que, si l’on s’arrête à l’analyse bi-variée, les femmes apparaissent nettement défavorisées par rapport aux hommes. Néanmoins, si l’on creuse et que l’on prend en compte les départements dans lesquels les candidats postulent, la différence homme/femme n’est plus significative. On se rend compte que si les femmes sont moins souvent admise à Berkley, c’est qu’elles postulent plus dans les départements les plus sélectifs et donc son plus souvent rejetée. On est face à ce que l’on appel le paradoxe de Simpson, le résultat primaire est contre-dit par le résultat approfondi prenant en compte plus de facteurs. D’un point de vue pratique, si on avait voulu assurer l’égalité hommes/femmes à Berkley à l’époque, il aurait été plus utile d’augmenter le nombre de places dans les départements dans lesquels elles postulent le plus ou les encourager à postuler sur d’autres moins sélectifs plutôt que de travailler sur une discrimination globale.

Allons chercher ces données sur la page wikipédia anglo-saxonne dédiée au paradoxe de Simpson.Commençons par intégrer le premier tableau dans R en utilisant les fonctions de rvest. read_html() crée la connexion avec la page où se trouve l’information. html_nodes() trie l’information sur la page pour isoler l’élément que vous voulez traiter. Ici, nous utilisons l’option xpath. Pour obtenir le chemin de l’élément, sélectionnez le tableau sur la page, effectuez un clique gauche, sélectionnez “inspecter”, puis dans la nouvelle fenêtre qui s’ouvre sélectionner “copier xpath”. htm_table() permet de restructurer les éléments importer pour l’intégrer dans un tableau.

url<-"https://en.wikipedia.org/wiki/Simpson%27s_paradox"
dat1<-url %>% 
    read_html() %>%
    html_nodes(xpath='//*[@id="mw-content-text"]/div[1]/table[1]') %>%
    html_table() %>% 
    as.data.frame()
dat1
##   Var.1        All    All.1        Men    Men.1      Women  Women.1
## 1       Applicants Admitted Applicants Admitted Applicants Admitted
## 2 Total     12,763      41%      8,442      44%      4,321      35%

L’information obtenue doit être retravailler pour permettre son traitement. Vous voudrions simplement une data frame avec une colonne pour le sexe des candidats et une pour leur statut (admis ou rejeté). Utilisons la fonction rep() pour générer les observations correspondant et vérifions si le résultat est conforme au tableau que nous avons scrappé avec les fonctions table() et addmargins().

dat1<-data.frame(
  sexe=c(rep('homme',8442),rep('femme',4321)),
  statut=c(rep('admis',round(8442*0.44)),
           rep('rejeté',round(8442*0.56)),
           rep('admis',round(4321*0.35)),
           rep('rejeté',round(4321*0.65))))
addmargins(table(dat1))
##        statut
## sexe    admis rejeté   Sum
##   femme  1512   2809  4321
##   homme  3714   4728  8442
##   Sum    5226   7537 12763

Maintenant que nous avons nos données, essayons d’illustrer la différence hommes/femmes concernant le taux d’admission à Berkley. Commençons par un diagramme à bâtons juxtaposés. Il s’obtient grâce au geom_bar() et l’option position “dodge”. Réalisons également quelques mises en formes de manière obtenir le graphe le plus parlant possible. Retenons notamment les couleurs de l’université (bleu et marron claire) pour nos barres.

ggplot(dat1,aes(x=sexe,fill=statut))+
  geom_bar(position='dodge')+
  geom_text(aes(label = ..count..),stat = "count", vjust = 5,colour = "white",
            position = position_dodge(width = .9))+
  geom_text(aes(label = statut,y=..count..),stat="count",vjust = 3,colour = "white",
            position = position_dodge(width = .9))+
  labs(title='Admissions à Berkley automne 1973',      
       caption='Source données: Bickel et al (1975)',
       y='Effectif')+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  theme_minimal()+
  theme(plot.title = element_text(hjust=0.5),
        plot.caption = element_text(face='italic'),
        axis.title.x = element_blank(),
        axis.title.y = element_text(hjust=0,angle=0),
        legend.position='none')

On voit nettement qu’il y a beaucoup plus de candidats hommes que femmes. Par contre, la différence en terme de taux de réussite est bien moins nette. Voyons ce qu’il en est, si on utilise des barres empilées. Nous les obtenons en indiquant ‘stack’ dans l’option position du geom_bar(). Pour rendre les indications textuelles incluent dans les bars plus faciles à manipuler, nous créons une variable les reprenant.

dat1<-dat1 %>% 
  mutate(et=ifelse(sexe=='femme'&statut=='admis','1512 admis',
            ifelse(sexe=='femme'&statut=='rejeté','2809 rejetés',
            ifelse(sexe=='homme'&statut=='admis','3461 admis','4981 rejetés'))))
ggplot(dat1,aes(x=sexe,fill=statut))+
  geom_bar(position='stack')+
  geom_text(aes(label = et,y=..count..),stat="count",vjust = 3,colour = "white",
            position = position_stack(vjust=1))+
  labs(title='Admissions à Berkley automne 1973',      
       caption='Source données: Bickel et al (1975)',
       y='Effectif')+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  theme_minimal()+
  theme(plot.title = element_text(hjust=0.5),
        plot.caption = element_text(face='italic'),
        axis.title.x = element_blank(),
        axis.title.y = element_text(hjust=0,angle=0),
        legend.position='none')

La différence en termes de proportions d’admissions entre hommes et femmes est maintenant clairement apparente. Néanmoins, on peine à en réaliser son ampleur du fait des tailles différentes des groupes définis en fonction du sexe. Voyons ce qu’il en est si on établit la hauteur des barres les représentant pour qu’elles soient la même. Pour cela, indiquons “fill” dans l’option position du geom_bar().

ggplot(dat1,aes(x=sexe,fill=statut))+
  geom_bar(position='fill')+
  geom_text(aes(label = et,y=..count..),stat="count",vjust = 3,colour = "white",
            position = position_fill(vjust=0.8))+
  labs(title='Admissions à Berkley automne 1973',      
       caption='Source données: Bickel et al (1975)',
       y='Effectif')+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  scale_y_continuous(labels=label_percent(accuracy = NULL))+
  theme_minimal()+
  theme(plot.title = element_text(hjust=0.5),
        plot.caption = element_text(face='italic'),
        axis.title.x = element_blank(),
        axis.title.y = element_text(hjust=0,angle=0),
        legend.position='none')

Cette fois, la différence de taux d’admission est bien mise en évidence. On voit que prés de 35% des candidates sont admises tandis que prés de 40% des candidats sont admis. On perd cependant en partie l’information concernant la taille des groupes hommes/femmes. Il ne reste que les indications textuelles que nous avons ajoutées pour intégrer cette information.

Le diagramme de Marimekko intégre l’information sur les effectifs en faisant varier la largeur des barres en fonction de ceux-ci. Présentons nos données à l’aide de ce type de graphe. Pour ce faire, nous allons utiliser le geom_rect() qui permet de tracer des rectangles à partir de l’indication des valeurs minimums et maximums des coordonnées associés pour chaque figure (x et y). Commençons par restructurer la base pour faciliter sa construction.

dat1_d<-data.frame(
  sex= c('femme', 'femme','homme', 'homme'),
  stat=c('admis','rejeté','admis','rejeté'),
  tx_reu = c(0.35, 0.65, 0.44, 0.56),
  effectif = c(1512, 2809, 3461, 4891))

Ceci fait, réalisons le graphe.

ggplot(dat1_d, aes(fill = stat)) +
  geom_rect(aes(xmin = cumsum(c(0,effectif[1:3])),
                xmax = cumsum(effectif),
                ymin = 0, ymax = tx_reu))+
  geom_text(aes(label = stat,y=tx_reu,x=c(800,3000,6000,10000)),
            vjust = 3,colour = "white")+
  geom_text(aes(label = sex,y=tx_reu,x=c(800,3000,6000,10000)),
            vjust = 6,colour = "white")+
  scale_x_continuous(breaks = seq(0,13000,1000))+
  scale_y_continuous(breaks = seq(0,0.70,0.05),limits = c(0,0.7),
                     labels=label_percent(accuracy = NULL))+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  labs(title='Admissions à Berkley automne 1973',      
       caption='Source données: Bickel et al (1975)')+
  coord_cartesian(expand=FALSE)+
  theme_minimal()+
  theme(plot.title = element_text(hjust=0.5),
        plot.caption = element_text(face='italic'),
        axis.title= element_blank(),
        legend.position='none')

L’ensemble est plus parlant. Un diagramme en mosaïque apparaît encore plus parlant. Il met en évidence à la fois la différence de tailles en proportion des groupes hommes/femmes et admis/rejeté. Pour le mettre en oeuvre, utilisons le geom_mosaic() du package ggmosaic. Indiquons comme esthétique (aes()) pour x l’intersection entre statut et sexe. Cela est rendu possible par la fonction product(). Indiquons également que nous souhaitons que les différents éléments du graphe soient colorés en fonction de statut (bleu pour les admis et marron pour les rejetés).

ggplot(dat1) + 
  geom_mosaic(aes(x=product(statut,sexe),fill=statut),position = 'identity')+
  labs(title='Admissions à Berkley automne 1973',
       subtitle = '(12 763 candidats)',
       caption='Source données: Bickel et al (1975)')+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  theme_mosaic()+
  theme(plot.title = element_text(hjust=0.5),
        plot.subtitle = element_text(hjust=0.5,face='italic'),
        plot.caption = element_text(face='italic'),
        axis.title = element_blank(),
        legend.position='none')
## Warning: `unite_()` was deprecated in tidyr 1.2.0.
## Please use `unite()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.

Les proportions sont bien rendues dans ce nouveau graphe. On voit clairement que le nombre de femmes candidates représente moins d’un tiers de l’ensemble et qu’elles sont admises à un taux un peu plus élevé que 33% alors que les hommes qui représentent plus des deux tiers de l’ensemble sont admis à un taux supérieur (plus proche des 40%).

Sans indications chiffrées, le diagramme en mosaïque rend bien compte de la relation entre les deux variables. Comme tout les graphes issus de ggplot, il peut être personnalisé. On peut notamment utiliser geom_mosaic_text() pour faire apparaître la valeur des différentes variables à l’intérieur du graphe et non sur les axes.

ggplot(dat1) + 
  geom_mosaic(aes(x=product(statut,sexe),fill=statut),position = 'identity')+
  geom_mosaic_text(aes(x=product(statut,sexe)),color='white',size=6)+
  labs(title='Admissions à Berkley automne 1973', 
       subtitle = '(12 763 candidats)',
       caption='Source données: Bickel et al (1975)')+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  theme_mosaic()+
  theme(plot.title = element_text(hjust=0.5),
        plot.subtitle = element_text(hjust=0.5,face='italic'),
        plot.caption = element_text(face='italic'),
        axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        legend.position='none')

Il y a une différence apparente entre les hommes et les femmes concernant l’admission à Berkley. Mais est-elle statistiquement significative? Pour le savoir, procédons à un test de différences de proportions (basé sur un khi2) à l’aide de la fonction prop.test().

table(dat1$statut,dat1$sexe) %>% prop.test() 
## 
##  2-sample test for equality of proportions with continuity correction
## 
## data:  .
## X-squared = 95.421, df = 1, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 95 percent confidence interval:
##  -0.09997492 -0.06676925
## sample estimates:
##    prop 1    prop 2 
## 0.2893226 0.3726947

La p-value est très petite, on rejette donc largement l’hypothèse d’égalité entre les proportions. La différence est statistiquement significative. On pourrait, sur cette base, conclure à une discrimination basée sur les goûts des jury d’admission qui seraient défavorables au femmes. Néanmoins, si on approfondit l’analyse pour prendre en compte les départements dans lesquels les étudiants ont candidaté, on voit que les choses sont différentes.

Introduisons cette nouvelles variables dans l’analyse. Pour cela, voyons le second tableau de la page wikipedia. Chargeons-le dans R.

url<-"https://en.wikipedia.org/wiki/Simpson%27s_paradox"
dat2<-url %>% 
    read_html() %>%
    html_nodes(xpath='//*[@id="mw-content-text"]/div[1]/table[2]') %>%
    html_table() %>% 
    as.data.frame()
dat2[1:8,]
##   Department        All    All.1        Men    Men.1      Women  Women.1
## 1 Department Applicants Admitted Applicants Admitted Applicants Admitted
## 2          A        933      64%        825      62%        108      82%
## 3          B        585      63%        560      63%         25      68%
## 4          C        918      35%        325      37%        593      34%
## 5          D        792      34%        417      33%        375      35%
## 6          E        584      25%        191      28%        393      24%
## 7          F        714       6%        373       6%        341       7%
## 8      Total       4526      39%       2691      45%       1835      30%

Notons qu’il ne porte que sur un sous-échantillon de notre base de départ. Considérons que celui-ci présente néanmoins les mêmes caractéristiques. Mettons-le en forme afin de pourvoir l’exploiter.

dat2<-data.frame(sexe=c(rep('homme',2691),rep('femme',1835)),
                 dep=c(rep('A',825),rep('B',560),rep('C',325),
                       rep('D',417),rep('E',191),rep('F',373),
                       rep('A',108),rep('B',25),rep('C',593),
                       rep('D',375),rep('E',393),rep('F',341)),
                 statut=c(rep('admis',round(825*0.62)-1),rep('rejeté',round(825*0.38)),
                       rep('admis',round(560*0.63)),rep('rejeté',round(560*0.37)),
                       rep('admis',round(325*0.37)),rep('rejeté',round(325*0.63)),
                       rep('admis',round(417*0.33)),rep('rejeté',round(417*0.67)),
                       rep('admis',round(191*0.28)),rep('rejeté',round(191*0.72)),
                       rep('admis',round(373*0.06)),rep('rejeté',round(373*0.94)),
                       rep('admis',round(108*0.82)),rep('rejeté',round(108*0.18)),
                       rep('admis',round(25*0.68)),rep('rejeté',round(25*0.32)),
                       rep('admis',round(593*0.34)),rep('rejeté',round(593*0.66)),
                       rep('admis',round(375*0.35)),rep('rejeté',round(375*0.65)),
                       rep('admis',round(393*0.24)),rep('rejeté',round(393*0.76)),
                       rep('admis',round(341*0.07)),rep('rejeté',round(341*0.93))))
addmargins(table(dat2$sexe,dat2$statut))
##        
##         admis rejeté  Sum
##   femme   557   1278 1835
##   homme  1197   1494 2691
##   Sum    1754   2772 4526

Ceci étant fait, on peut réaliser un diagramme en mosaïque pour vérifier si notre sous-échantillon on reprouve bien le même type de différences hommes/femmes que dans le cadre général.

ggplot(dat2) + 
  geom_mosaic(aes(x=product(statut,sexe),fill=statut))+
  labs(title='Admissions à Berkley automne 1973', 
       subtitle = '(4 526 candidats)',
       caption='Source données: Bickel et al (1975)')+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  theme_mosaic()+
  theme(plot.title = element_text(hjust=0.5),
        plot.subtitle = element_text(hjust=0.5,face='italic'),
        plot.caption = element_text(face='italic'),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        legend.position = 'none') 

Il semble bien que ce soit le cas. On peut donc continuer l’analyse en intégrant notre nouvelle variable.

Voyons ce que donne le diagramme mosaïque. Cette fois, la déclaration de l’élément principale à représenter (x) comprendra trois variables (statut, sexe et dep) que l’on introduit conjointement avec la fonction product(). Indiquons pour faciliter la lecture que nous ferons varier la couleur (fill) en fonction de statut et le niveau de transparence (alpha) de ces couleurs en fonction de sexe. Utilisons l’option divider pour renforcer les séparations verticales et horizontales dans le graphe.

ggplot(dat2) + 
  geom_mosaic(aes(x=product(statut,sexe,dep),fill=statut,alpha=sexe),
              divider=c("vspine","hspine","hspine"))+
  labs(title='Admissions à Berkley automne 1973',
       subtitle = '(4 526 candidats)',
       caption='Source données: Bickel et al (1975)')+
  scale_alpha_manual(values =c(0.9,0.6))+
  scale_fill_manual(values=c('#0000FF','#BEA226'))+
  theme_mosaic()+
  theme(plot.title = element_text(hjust=0.5),
        plot.subtitle = element_text(hjust=0.5,face='italic'),
        plot.caption = element_text(face='italic'),
        axis.title.x = element_blank(),
        axis.text.x = element_text(angle = 90, hjust = 1,vjust = 0.5,size=10),
        axis.title.y = element_blank(),
        legend.position = 'none') 

On voit que les femmes ne sont pas moins fréquemment admises dans tout les départements. Leur taux d’admission est plus important que celui des hommes dans les départements A, B, D et F. Néanmoins, elles sont proportionnellement moins nombreuses à y postuler. Elles sont plus nombreuses à postuler dans les département C et E où le taux d’admission est en générale relativement bas et où elles sont légèrement moins fréquemment reçues que les hommes. On peut dire qu’elles s’orientent sur les départements les plus sélectifs et donc sont plus souvent rejetées.

Bref, les choses semblent plus compliquées. Voyons ce qu’il en ait si on pratique des tests statistiques. Commençons par le simple test de différence de proportions.

table(dat2$statut,dat2$sexe) %>% prop.test() 
## 
##  2-sample test for equality of proportions with continuity correction
## 
## data:  .
## X-squared = 91.147, df = 1, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 95 percent confidence interval:
##  -0.1725624 -0.1143958
## sample estimates:
##    prop 1    prop 2 
## 0.3175599 0.4610390

Comme sur l’échantillon précédant, on retrouve une différence significative (p-value très faible). On rejette l’hypothèse d’égalité de taux d’admission entre les hommes et les femmes. Les femmes semblent défavorisées lors de la sélection.

Le test pratiqué ne permet pas d’inclure dep dans l’analyse. Pour palier à la difficulté, utilisons une régression logistique (grâce à la fonction glm()). Nous l’estimons, pour avoir une référence pour suite, sur la seule variable sexe (après quelques transformations rapides afin d’avoir des variables binaires avec pour références admis et femme).

dat2$st_d<-dat2$statut=='admis'
dat2$sex_d<-dat2$sexe=='femme'
dat2 %>% glm(formula=st_d~sex_d,
             family = binomial(logit)) %>% 
  summary()
## 
## Call:
## glm(formula = st_d ~ sex_d, family = binomial(logit), data = .)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.0849  -1.0849  -0.8506   1.2729   1.5442  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -0.22164    0.03879  -5.714 1.11e-08 ***
## sex_dTRUE   -0.60885    0.06389  -9.529  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 6043.4  on 4525  degrees of freedom
## Residual deviance: 5950.4  on 4524  degrees of freedom
## AIC: 5954.4
## 
## Number of Fisher Scoring iterations: 4

Le coefficient est négatif et statistiquement significatif. Cela confirme que les femmes sont moins fréquemment admises à Berkley que les hommes. On peut utiliser binomial()$linkin() sur la constante pour obtenir la probabilité estimée par le modèle d’être admis pour un homme et le coefficient de la variable sex_d pour obtenir celle prévalant pour une femme.

binomial()$linkinv(-0.221)
## [1] 0.4449738
binomial()$linkinv(-0.608)
## [1] 0.3525156

D’après le modèle, un homme aurait 44,5% de chance d’être admis tandis qu’une femme n’aurait que 35,2% de chance d’être admises.

Incluons la variable dep dans le modèle pour voir si l’effet perdure lorsque l’on contrôle par le département dans lequel l’individu candidate.

dat2 %>% glm(formula=st_d~sex_d+dep,
             family = binomial(logit)) %>% 
  summary()
## 
## Call:
## glm(formula = st_d ~ sex_d + dep, family = binomial(logit), data = .)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -1.4754  -0.9307  -0.3741   0.9588   2.3615  
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  0.57729    0.06895   8.373   <2e-16 ***
## sex_dTRUE    0.10061    0.08084   1.244    0.213    
## depB        -0.03867    0.10981  -0.352    0.725    
## depC        -1.25832    0.10660 -11.804   <2e-16 ***
## depD        -1.29020    0.10579 -12.195   <2e-16 ***
## depE        -1.73505    0.12609 -13.760   <2e-16 ***
## depF        -3.30209    0.16996 -19.428   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 6043.4  on 4525  degrees of freedom
## Residual deviance: 5188.6  on 4519  degrees of freedom
## AIC: 5202.6
## 
## Number of Fisher Scoring iterations: 5

Le coefficient associé à sex_d (le fait pour un candidat d’être une femme) n’est plus significatif. Il n’y a pas de différence concernant la probabilité d’admission entre hommes et femmes si l’on contrôle en fonction du département dans lequel elle ou il postule.

On est face au paradoxe de Simpson qui est bien illustrer par nos diagrammes en mosaïque que l’on peut réunir en une seul figure avec le package pacthwork.

m1<-ggplot(dat2) + 
      geom_mosaic(aes(x=product(statut,sexe),fill=statut,alpha=sexe))+
      scale_alpha_manual(values =c(0.9,0.6))+
      scale_fill_manual(values=c('#0000FF','#BEA226'))+
      theme_mosaic()+
      theme(plot.title = element_text(hjust=0.5),
            plot.subtitle = element_text(hjust=0.5,face='italic'),
            plot.caption = element_text(face='italic'),
            axis.title.x = element_blank(),
            axis.title.y = element_blank(),
            legend.position = 'none') 
m2<-ggplot(dat2) + 
     geom_mosaic(aes(x=product(statut,sexe,dep),fill=statut,alpha=sexe),
                 divider=c("vspine","hspine","hspine"))+
     scale_alpha_manual(values =c(0.9,0.6))+
     scale_fill_manual(values=c('#0000FF','#BEA226'))+
     theme_mosaic()+
     theme(plot.title = element_text(hjust=0.5),
           plot.subtitle = element_text(hjust=0.5,face='italic'),
           plot.caption = element_text(face='italic'),
           axis.title.x = element_blank(),
           axis.text.x = element_text(angle = 90, hjust = 1,vjust = 0.5,size=10),
           axis.title.y = element_blank(),
           axis.text.y = element_blank(),
           axis.ticks.y = element_blank(),
           legend.position = 'none')
m1+m2+plot_annotation(
  title = 'Illustrations du Paradox de Simpson',
  subtitle = 'Admission à Berkley automne 1973 - 4526 candidats',
  caption = 'Source données: Bickel et al (1975)') &
  theme(plot.title = element_text(hjust=0.5),
        plot.subtitle = element_text(hjust=0.5,face='italic'),
        plot.caption= element_text(face='italic'))

Les diagrammes en mosaïque sont performant pour illustrer les liens entre variables catégorielles. Ils donnent une vision claire des effectifs croisés au travers de la différence de surface des rectangles qui les composent. Ils présentent néanmoins des limites. La première est que l’œil humain n’est pas très performant lorsqu’il s’agit de relever de faibles différences de surfaces. Il n’est pas non plus très bon pour évaluer les proportions de ces différences. La surface correspondant aux hommes admis est 3,15 fois celle des femmes admises dans le graphe sans les départements ((1197x2691)/(557x1835))… La seconde limites est qu’ils deviennent vite illisibles si les variables mobilisées intègrent trop de catégories.


  1. P.J. Bickel, E.A. Hammel and J.W. O’Connell (1975). “Sex Bias in Graduate Admissions: Data From Berkeley” (PDF). Science. 187 (4175): 398–404. Bibcode:1975Sci…187..398B. doi:10.1126/science.187.4175.398. PMID 17835295. S2CID 15278703.↩︎