Données sur les thèses de doctorat et mémoires de maîtrise au Québec
Jupyter Notebook
Switch branches/tags
Nothing to show
Clone or download
Latest commit 9a3ac9c Mar 11, 2017
Permalink
Failed to load latest commit information.
theses_files diagramme à moustache -> fichier local Mar 11, 2017
.gitignore retrait des ? Sep 4, 2016
Readme.md source image Mar 11, 2017
THESES-TOTAL.csv MàJ Jan 13, 2017
theses.ipynb MàJ Jan 13, 2017

Readme.md

Thèses et mémoires du Québec

Quelques données sur les doctorats et maîtrises publiés dans les universités québécoises depuis les années 1990


*Data on theses and dissertations published in Québec universities in the last 25 years*

%matplotlib inline
import csv, re, random
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from scipy import stats, integrate
import seaborn as sns

On commence par demander à pandas d'avaler le fichier CSV qui contient toutes nos données et de les placer dans la variable theses.

theses = pd.read_csv("THESES-TOTAL.csv")

On fait ensuite, toujours grâce à pandas, une première analyse rapide du nombre de pages selon le type de document (doctorat ou maîtrise). Tout de suite, on a:

  • le nombre total de documents dans chacun de ces deux types
  • les valeurs extrêmes (min et max)
  • la moyenne et la médiane (50%)
  • une idée de la distribution du nombre de pages par quartile
parType = theses.groupby("type").nbPages
parType.describe()
type           
doctorat  count    15097.000000
          mean       251.340929
          std        116.638041
          min         46.000000
          25%        172.000000
          50%        226.000000
          75%        302.000000
          max       1578.000000
maîtrise  count    40486.000000
          mean       133.282023
          std         54.083320
          min         19.000000
          25%         98.000000
          50%        124.000000
          75%        157.000000
          max        744.000000
dtype: float64

On demande ensuite à matplotlib de faire un premier graphique. C'est un histogramme de la distribution du nombre de pages des maîtrises et doctorats par tranche de 10 pages, puisqu'on fait 50 colonnes («bins») dans un intervalle («range») qui va de 10 à 510. Le paramètre alpha indique que les colonnes auront une transparence de 50%.

parType.hist(bins=50,histtype="bar",range=(10,510), alpha=0.5)
plt.legend(["Doctorats","Maîtrises"])
plt.title("Distribution des thèses et mémoires\npar nombre de pages",size=20)
<matplotlib.text.Text at 0x115e74128>

png


Les doctorats


Commençons par analyser seulement les doctorats en les regroupant tous dans une variable du même nom. Pandas peut nous décrire quelques-unes des données contenues dans ce sous-ensemble:

  • l'année à laquelle le doctorat a été déposé
  • son nombre de pages
  • la longueur de son titre
doctorats = theses.query("type == 'doctorat'")
doctorats.describe()
annee octets nbPages longTitre
count 15097.000000 1.403500e+04 15097.000000 15097.000000
mean 2008.445320 1.757504e+07 251.340929 107.015566
std 6.029071 2.936516e+07 116.638041 41.183641
min 1990.000000 5.946900e+04 46.000000 14.000000
25% 2006.000000 3.945502e+06 172.000000 77.000000
50% 2010.000000 7.671272e+06 226.000000 102.000000
75% 2013.000000 1.641865e+07 302.000000 131.000000
max 2016.000000 5.581489e+08 1578.000000 378.000000

C'est bien d'avoir des données sur l'ensemble des doctorats au Québec. Mais je suis curieux de savoir comment le nombre de pages de ces doctorats varie en fonction de l'université dans laquelle ils ont été réalisés.

Pandas nous aide ici encore en permettant d'effectuer un regroupement par université que j'ai placé dans une variable appelée doctoratsUniv.

doctoratsUniv = doctorats.groupby("universite")
doctoratsUniv.describe()
annee longTitre nbPages octets
universite
Concordia count 2079.000000 2079.000000 2079.000000 2.057000e+03
mean 2005.673401 89.589707 230.285233 8.462193e+06
std 7.269765 34.370518 96.823321 8.644034e+06
min 1990.000000 14.000000 61.000000 3.519070e+05
25% 2000.000000 65.000000 162.000000 4.037521e+06
50% 2008.000000 85.000000 210.000000 6.642033e+06
75% 2012.000000 108.000000 276.000000 1.041637e+07
max 2015.000000 261.000000 1112.000000 1.678755e+08
HEC Montréal count 286.000000 286.000000 286.000000 0.000000e+00
mean 2006.437063 92.804196 258.132867 NaN
std 6.136565 37.508784 145.435618 NaN
min 1990.000000 26.000000 61.000000 NaN
25% 2003.000000 62.250000 152.000000 NaN
50% 2007.000000 89.000000 220.500000 NaN
75% 2012.000000 118.000000 337.250000 NaN
max 2016.000000 212.000000 1430.000000 NaN
INRS count 499.000000 499.000000 499.000000 4.730000e+02
mean 2008.030060 122.625251 246.112224 2.360549e+07
std 5.860930 40.343130 88.203599 3.143506e+07
min 1990.000000 37.000000 87.000000 6.946860e+05
25% 2005.000000 95.000000 182.500000 4.665799e+06
50% 2009.000000 118.000000 231.000000 1.036514e+07
75% 2013.000000 146.500000 291.500000 2.675130e+07
max 2016.000000 303.000000 682.000000 2.037039e+08
McGill count 1927.000000 1927.000000 1927.000000 1.927000e+03
mean 2004.746238 89.756098 246.120394 1.071442e+07
std 7.590674 33.750700 104.115630 1.170955e+07
min 1990.000000 16.000000 47.000000 4.112780e+05
25% 1998.000000 65.000000 182.000000 4.445412e+06
50% 2006.000000 85.000000 225.000000 7.978906e+06
... ... ... ... ... ...
Université Laval std 3.234690 41.847277 120.156801 4.535230e+07
min 2002.000000 14.000000 57.000000 4.692270e+05
25% 2008.000000 84.000000 174.000000 5.303671e+06
50% 2011.000000 109.000000 232.000000 2.043751e+07
75% 2014.000000 137.000000 311.000000 5.390143e+07
max 2016.000000 378.000000 1478.000000 5.581489e+08
Université de Montréal count 2641.000000 2641.000000 2641.000000 2.641000e+03
mean 2010.151079 109.820144 283.244983 9.042001e+06
std 3.687238 38.697944 121.221355 1.797919e+07
min 1990.000000 21.000000 49.000000 1.110980e+05
25% 2008.000000 81.000000 202.000000 2.180442e+06
50% 2010.000000 107.000000 260.000000 4.277027e+06
75% 2013.000000 135.000000 338.000000 8.554617e+06
max 2015.000000 259.000000 1578.000000 3.339740e+08
Université de Sherbrooke count 1724.000000 1724.000000 1724.000000 1.724000e+03
mean 2008.096868 117.897332 234.301044 1.658168e+07
std 5.812250 43.160102 105.855871 3.248490e+07
min 1990.000000 21.000000 46.000000 5.946900e+04
25% 2004.000000 88.000000 163.000000 5.499002e+06
50% 2009.000000 111.000000 208.000000 8.366110e+06
75% 2013.000000 142.000000 276.000000 1.283679e+07
max 2016.000000 351.000000 826.000000 3.400589e+08
École Polytechnique count 576.000000 576.000000 576.000000 5.760000e+02
mean 2012.612847 96.097222 201.854167 8.199000e+06
std 1.856910 31.753029 74.976446 1.215289e+07
min 2009.000000 25.000000 84.000000 5.815810e+05
25% 2011.000000 73.000000 151.000000 2.738251e+06
50% 2013.000000 93.000000 186.000000 5.302887e+06
75% 2014.000000 115.250000 233.000000 9.444866e+06
max 2016.000000 200.000000 633.000000 2.049431e+08

104 rows × 4 columns


Classons maintenant les universités en fonction du nombre médian de pages de leurs doctorats, exercice intéressant en soi qui sera également utile pour l'étape suivante.

medianesDoctoratsUniv = doctoratsUniv["nbPages"].median().sort_values(ascending=False)
medianesDoctoratsUniv
universite
UQAM                        269.0
Université de Montréal      260.0
UQAC                        243.0
UQO                         238.5
Université Laval            232.0
INRS                        231.0
McGill                      225.0
UQAT                        220.5
HEC Montréal                220.5
Concordia                   210.0
Université de Sherbrooke    208.0
École Polytechnique         186.0
UQTR                        153.5
Name: nbPages, dtype: float64

Pour illustrer la distribution du nombre de pages des doctorats par université, le meilleur type de graphique est peut-être le box plot, qu'on peut traduire par diagramme de quartiles... ou ce que les Français ont baptisé des boîtes à moustaches (source de l'image ci-dessous : Statistique Canada).

Ces boîtes permettent d'afficher une distribution qui a été découpée en quartiles.
Les deuxième et troisième quartiles, ceux qui se trouvent de part et d'autre de la médiane, sont représentés par deux rectangles, les boîtes.
Les premier et dernier quartiles sont, quant à eux, représentés par des lignes, les moustaches.
Des valeurs excentriques peuvent enfin être représentés par des points à gauche ou à droite des lignes.

J'ai essayé d'utiliser le langage R pour en produire, comme l'a fait Markus Beck. Mais j'ai été incapable d'arriver à des résultats satisfaisants.

Après avoir essayé les librairies matplotlib et bokeh, j'ai trouvé seaborn beaucoup plus facile à utiliser.
Le code ci-dessous est relativement facile à comprendre. Matplotlib contrôle la taille finale du graphique au moyen de la méthode plt.figure, puis seaborn fait tout le reste. On remarque notamment que la méthode sns.boxplot a un paramètre qui permet d'ordonner nos boîtes (order), paramètre que j'ai alimenté avec l'index de la variable medianesDoctoratsUniv créé juste ci-dessus.

Au final, on a une idée de la distribution du nombre de pages des doctorats, par université. C'est à l'UQAM que les professeurs travaillent le plus (si on se fie au nombre de pages qu'ils doivent lire)... ou le moins (si on se fie au nombre de pages qu'ils laissent leurs doctorants écrire).

sns.set()
plt.figure(figsize=(10, 15))
sns.set_style("darkgrid", {
        "axes.facecolor": "lightskyblue",
        "font.family": [u"Bitstream Vera Sans"]
    })
couleurs = sns.light_palette("turquoise", n_colors=13, reverse=True)
boiteDoc = sns.boxplot(y="universite",
                       x="nbPages",
                       data=doctorats,
                       palette=couleurs,
                       order=medianesDoctoratsUniv.index
                      )
boiteDoc.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
boiteDoc.grid(b=True, which='major', color='w', linewidth=2.0)
boiteDoc.grid(b=True, which='minor', color='w', linewidth=0.5)
boiteDoc.set(ylabel="Université",
             xlabel="Distribution du nombre de pages",
             xlim=(0,750),
             title="Nombre de pages des doctorats par université\n"
            )
[<matplotlib.text.Text at 0x117886278>,
 (0, 750),
 <matplotlib.text.Text at 0x1165ab978>,
 <matplotlib.text.Text at 0x11788d048>]

png


On peut aussi créer un autre graphique à moustaches intéressant en regroupant les doctorats par discipline, plutôt que par université.
On commence par créer une variable qui va nous permetter d'ordonner les disciplines en fonction de la médiane du nombre de pages (medianesDoctoratsDiscipline).

doctoratsDiscipline = doctorats.groupby("discipline")
medianesDoctoratsDiscipline = doctoratsDiscipline["nbPages"].median().sort_values(ascending=False)
medianesDoctoratsDiscipline
discipline
Droit                                 459.0
Relations industrielles               420.0
Histoire                              412.0
Anthropologie                         407.5
Traduction                            394.5
Études classiques                     392.5
Études françaises                     372.0
Cinéma                                366.0
Histoire de l'art                     364.0
Littérature                           355.0
Sociologie                            350.0
Science politique                     346.0
Religion/théologie                    340.5
Pédagogie                             336.0
Communication                         335.0
Aménagement/urbanisme                 330.0
Gérontologie                          329.0
Études islamiques                     328.5
Philosophie                           324.0
Sciences humaines générales           315.0
Administration publique               314.0
Études hispaniques                    313.0
Linguistique                          308.0
Sciences de l'information             300.0
Travail social                        294.5
Géographie                            293.0
Nutrition                             291.5
Arts visuels                          289.0
Santé publique et communautaire       287.0
Éducation                             286.0
                                      ...  
Génie minier                          220.0
Orientation                           217.0
Génie de l'environnement              216.5
Télécommunications                    207.0
Musique                               206.5
Génie chimique                        204.0
Génie industriel                      202.0
Biotechnologie agricole               201.0
Comptabilité                          200.0
Génie mécanique                       199.0
Génie physique                        199.0
Agriculture et pêcheries              198.5
Ingénierie biomédicale                196.5
Sciences de l'environnement           194.0
Biologie                              190.0
Radiologie et imagerie biomédicale    188.0
Marketing                             187.5
Géomatique et télédétection           187.0
Informatique                          185.0
Sylviculture/foresterie               184.5
Météorologie                          182.5
Physique                              178.0
Génie électrique                      178.0
Génie logiciel                        173.0
Médecine dentaire                     171.0
Psychologie                           166.0
Économie                              157.0
Finance                               156.5
Statistique                           152.0
Mathématiques                         133.5
Name: nbPages, dtype: float64

Puis on fait un diagramme par quartiles de la même façon qu'on vient de le faire avec les universités.
Le résultat est un graphique complexe, mais riche en information. C'est en droit que les doctorants sont le plus prolixes, alors que les mathématiciens et statisticiens ont davantage l'habitude d'être right to the point.

sns.set()
sns.set_context("poster")
sns.set(font_scale=2)
plt.figure(figsize=(20, 35))
sns.set_style("darkgrid", {
        "axes.facecolor": "lightskyblue",
        "font.family": [u"Bitstream Vera Sans"]
    })
couleurs = sns.light_palette("turquoise", n_colors=93, reverse=True)
boiteDoc = sns.boxplot(y="discipline",
                       x="nbPages",
                       data=doctorats,
                       palette=couleurs,
                       order=medianesDoctoratsDiscipline.index
                      )
boiteDoc.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator(n=10))
boiteDoc.grid(b=True, which='major', color='w', linewidth=3.0)
boiteDoc.grid(b=True, which='minor', color='w', linewidth=1)
boiteDoc.set(ylabel="Discipline",
             xlabel="Distribution du nombre de pages",
             xlim=(0,750),
             title="Nombre de pages des doctorats par discipline\nUniversités du Québec (de 1990 à 2016)\n"
            )
[<matplotlib.text.Text at 0x119705ba8>,
 (0, 750),
 <matplotlib.text.Text at 0x119722748>,
 <matplotlib.text.Text at 0x119b59e10>]

png


Les maîtrises


On peut maintenant faire la même chose pour les maîtrises en suivant exactement les mêmes étapes.

maitrises = theses.query("type == 'maîtrise'")
maitrises.describe()
annee octets nbPages longTitre
count 40486.000000 3.477800e+04 40486.000000 40486.000000
mean 2007.033691 8.790473e+06 133.282023 102.193672
std 6.312805 1.820470e+07 54.083320 39.216376
min 1990.000000 9.075000e+03 19.000000 4.000000
25% 2004.000000 2.322921e+06 98.000000 75.000000
50% 2008.000000 4.191776e+06 124.000000 98.000000
75% 2012.000000 8.056662e+06 157.000000 125.000000
max 2016.000000 1.916892e+09 744.000000 345.000000
maitrisesUniv = maitrises.groupby("universite")
maitrisesUniv.describe()
annee longTitre nbPages octets
universite
Concordia count 7210.000000 7210.000000 7210.000000 7.147000e+03
mean 2004.673786 83.308460 125.848128 5.177932e+06
std 6.978006 32.854020 49.743067 2.473131e+07
min 1990.000000 4.000000 19.000000 9.075000e+03
25% 2000.000000 61.000000 94.000000 2.440756e+06
50% 2006.000000 80.000000 117.000000 3.859451e+06
75% 2010.000000 103.000000 149.000000 5.704982e+06
max 2016.000000 251.000000 666.000000 1.916892e+09
HEC Montréal count 2691.000000 2691.000000 2691.000000 0.000000e+00
mean 2004.829431 98.866592 146.237087 NaN
std 5.603063 35.700203 66.552327 NaN
min 1990.000000 21.000000 27.000000 NaN
25% 2001.000000 74.000000 97.000000 NaN
50% 2005.000000 94.000000 136.000000 NaN
75% 2009.000000 119.000000 181.000000 NaN
max 2015.000000 289.000000 671.000000 NaN
INRS count 852.000000 852.000000 852.000000 8.020000e+02
mean 2006.393192 118.221831 135.187793 1.380241e+07
std 6.125526 38.144186 54.682525 2.036042e+07
min 1990.000000 39.000000 46.000000 4.846760e+05
25% 2003.000000 89.000000 98.000000 2.168610e+06
50% 2007.000000 115.000000 124.000000 4.917306e+06
75% 2011.000000 141.000000 158.250000 1.571059e+07
max 2016.000000 259.000000 572.000000 2.258889e+08
McGill count 3169.000000 3169.000000 3169.000000 3.169000e+03
mean 2003.526033 87.065636 113.933733 5.120333e+06
std 7.550171 33.343854 35.053225 6.688783e+06
min 1990.000000 9.000000 27.000000 1.148270e+05
25% 1997.000000 63.000000 91.000000 2.421128e+06
50% 2004.000000 82.000000 109.000000 4.120969e+06
... ... ... ... ... ...
Université Laval std 3.094363 39.890720 53.539320 1.939081e+07
min 2003.000000 6.000000 26.000000 2.191560e+05
25% 2008.000000 82.000000 93.500000 3.310624e+06
50% 2010.000000 106.000000 120.000000 1.363568e+07
75% 2013.000000 133.000000 153.000000 2.798163e+07
max 2016.000000 345.000000 743.000000 2.655805e+08
Université de Montréal count 5368.000000 5368.000000 5368.000000 5.368000e+03
mean 2009.920268 105.663376 134.533905 4.505311e+06
std 3.593720 36.558156 47.373174 1.177802e+07
min 1990.000000 13.000000 25.000000 6.659300e+04
25% 2008.000000 79.000000 104.000000 1.077788e+06
50% 2010.000000 103.000000 128.000000 2.077272e+06
75% 2013.000000 129.000000 157.000000 4.023963e+06
max 2015.000000 288.000000 541.000000 2.880010e+08
Université de Sherbrooke count 4640.000000 4640.000000 4640.000000 4.640000e+03
mean 2006.019397 110.667457 140.139871 1.015948e+07
std 6.288464 39.815207 54.996114 1.797599e+07
min 1990.000000 14.000000 30.000000 3.310720e+05
25% 2001.000000 83.000000 104.000000 3.317203e+06
50% 2007.000000 107.000000 130.000000 5.174308e+06
75% 2011.000000 134.000000 165.000000 7.816884e+06
max 2016.000000 305.000000 712.000000 2.953644e+08
École Polytechnique count 1046.000000 1046.000000 1046.000000 1.046000e+03
mean 2012.322180 99.830784 135.810707 7.651716e+06
std 1.838042 30.244159 53.423384 2.009079e+07
min 2009.000000 26.000000 39.000000 2.678300e+05
25% 2011.000000 79.000000 100.000000 2.059766e+06
50% 2012.000000 96.000000 123.500000 3.616986e+06
75% 2014.000000 118.000000 159.000000 7.254857e+06
max 2016.000000 195.000000 496.000000 4.822821e+08

104 rows × 4 columns

medianesMaitrisesUniv = maitrises.groupby("universite")["nbPages"].median().sort_values(ascending=False)
medianesMaitrisesUniv
universite
UQAC                        144.0
HEC Montréal                136.0
UQAM                        135.0
UQAT                        131.0
Université de Sherbrooke    130.0
Université de Montréal      128.0
INRS                        124.0
École Polytechnique         123.5
Université Laval            120.0
UQTR                        118.0
UQO                         117.5
Concordia                   117.0
McGill                      109.0
Name: nbPages, dtype: float64
sns.set()
plt.figure(figsize=(10, 15))
sns.set_style("darkgrid", {
        "axes.facecolor": "khaki",
        "font.family": [u"Bitstream Vera Sans"]
    })
couleurs = sns.light_palette("olive", n_colors=13, reverse=True)
boiteDoc = sns.boxplot(y="universite",
                       x="nbPages",
                       data=maitrises,
                       palette=couleurs,
                       order=medianesMaitrisesUniv.index
                      )
boiteDoc.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator())
boiteDoc.grid(b=True, which='major', color='w', linewidth=2.0)
boiteDoc.grid(b=True, which='minor', color='w', linewidth=0.5)
boiteDoc.set(ylabel="Université",
             xlabel="Distribution du nombre de pages",
             xlim=(0,350),
             title="Nombre de pages des maîtrises par université\n"
            )
[<matplotlib.text.Text at 0x117141b00>,
 (0, 350),
 <matplotlib.text.Text at 0x11e835ef0>,
 <matplotlib.text.Text at 0x11717a470>]

png

medianesMaitrisesDiscipline = maitrises.groupby("discipline")["nbPages"].median().sort_values(ascending=False)
medianesMaitrisesDiscipline
discipline
Design                               179.0
Danse                                176.0
Aménagement/urbanisme                164.0
Sciences infirmières                 158.5
Management/gestion                   158.0
Droit                                158.0
Gérontologie                         157.0
Génie (général)                      157.0
Anthropologie                        154.5
Relations industrielles              152.0
Génie civil                          149.0
Travail social                       148.0
Sociologie                           146.0
Sciences humaines générales          145.0
Pédagogie                            144.0
Études juives                        143.5
Sciences de l'information            143.0
Histoire                             143.0
Géographie                           141.0
Linguistique                         139.0
Éducation                            138.0
Génie minier                         137.5
Histoire de l'art                    137.5
Géologie                             136.0
Architecture                         135.5
Communication                        135.0
Science politique                    135.0
Religion/théologie                   134.0
Administration publique              133.0
Criminologie                         132.5
                                     ...  
Géomatique et télédétection          110.0
Théâtre                              110.0
Génétique                            108.0
Épidémiologie                        108.0
Anatomie                             108.0
Informatique                         108.0
Médecine expérimentale               108.0
Pathologie                           107.0
Psychiatrie                          106.5
Sciences de l'environnement          106.0
Comptabilité                         105.0
Marketing                            105.0
Psychologie                          103.0
Agriculture et pêcheries             103.0
Sylviculture/foresterie              102.0
Kinésiologie                         101.0
Statistique                          100.0
Études des sciences et techniques    100.0
Neurologie                           100.0
Météorologie                          99.5
Physique                              99.0
Études italiennes                     97.0
Biologie                              94.0
Mathématiques                         94.0
Psychoéducation                       94.0
Chirurgie                             89.0
Télécommunications                    81.5
Économie                              80.0
Arts visuels                          79.0
Finance                               69.0
Name: nbPages, dtype: float64
sns.set()
sns.set_context("poster")
sns.set(font_scale=2)
plt.figure(figsize=(20, 35))
sns.set_style("darkgrid", {
        "axes.facecolor": "khaki",
        "font.family": [u"Bitstream Vera Sans"]
    })
couleurs = sns.light_palette("olive", n_colors=102, reverse=True)
boiteMait = sns.boxplot(y="discipline",
                       x="nbPages",
                       data=maitrises,
                       palette=couleurs,
                       order=medianesMaitrisesDiscipline.index
                      )
boiteMait.get_xaxis().set_minor_locator(mpl.ticker.AutoMinorLocator(n=5))
boiteMait.grid(b=True, which='major', color='w', linewidth=3.0)
boiteMait.grid(b=True, which='minor', color='w', linewidth=1)
boiteMait.set(ylabel="Discipline",
             xlabel="Distribution du nombre de pages",
             xlim=(0,350),
             title="Nombre de pages des maîtrises par discipline\nUniversités du Québec (de 1990 à 2016)\n"
            )
[<matplotlib.text.Text at 0x120ad29b0>,
 (0, 350),
 <matplotlib.text.Text at 0x1202b3748>,
 <matplotlib.text.Text at 0x1202b0978>]

png


Un dernier graphique, juste pour le kik

Seaborn permet aussi de tracer des graphiques en forme de violon, ou violin plots. Cela ressemble à des diagrammes à moustaches, sauf qu'on n'y découpe pas la matière en quartiles. On y donne plutôt un aperçu de la densité réelle de la distribution.
Il est aussi possible de représenter deux catégories sur chaque violon, ce qui est parfait pour le cas qui nous intéresse, puisqu'on a justement deux catégories à représenter: les maîtrises et les doctorats. Elles sont identifiées par le paramètre hue de la méthode sns.violinplot dans le code ci-dessous.

sns.set_style("darkgrid")
sns.set_context("poster")
plt.figure(figsize=(10, 15))
violon = sns.violinplot(y="universite", x="nbPages", data=theses, bw=.1, hue="type", split=True)
violon.set(ylabel="Université",
             xlabel="Distribution du nombre de pages",
             xlim=(-100,1400),
             title="Nombre de pages des maîtrises et des doctorats par université\nUniversités du Québec (de 1990 à 2016)\n"
            )
sns.despine()

png