La version originale de ce chapitre est une reprise, avec l’aimable autorisation de son auteur, d’un article de Nicolas Robette intitulé L’analyse de séquences : une introduction avec le logiciel R et le package TraMineR et publié sur le blog Quanti (http://quanti.hypotheses.org/686/).

Depuis les années 1980, l’étude quantitative des trajectoires biographiques (life course analysis) a pris une ampleur considérable dans le champ des sciences sociales. Les collectes de données micro-individuelles longitudinales se sont développées, principalement sous la forme de panels ou d’enquêtes rétrospectives. Parallèlement à cette multiplication des données disponibles, la méthodologie statistique a connu de profondes évolutions. L’analyse des biographies (event history analysis) — qui ajoute une dimension diachronique aux modèles économétriques mainstream — s’est rapidement imposée comme l’approche dominante : il s’agit de modéliser la durée des situations ou le risque d’occurrence des événements.

L’analyse de séquences

Cependant, ces dernières années ont vu la diffusion d’un large corpus de méthodes descriptives d’analyse de séquences, au sein desquelles l’appariement optimal (optimal matching) occupe une place centrale1. L’objectif principal de ces méthodes est d’identifier — dans la diversité d’un corpus de séquences constituées de séries d’états successifs — les régularités, les ressemblances, puis le plus souvent de construire des typologies de « séquences-types ». L’analyse de séquences constitue donc un moyen de décrire mais aussi de mieux comprendre le déroulement de divers processus.

La majeure partie des applications de l’analyse de séquences traite de trajectoires biographiques ou de carrières professionnelles. Dans ces cas, chaque trajectoire ou chaque carrière est décrite par une séquence, autrement dit par une suite chronologiquement ordonnée de « moments » élémentaires, chaque moment correspondant à un « état » déterminé de la trajectoire (par exemple, pour les carrières professionnelles : être en emploi, au chômage ou en inactivité). Mais on peut bien sûr imaginer des types de séquences plus originaux : Andrew Abbott2, le sociologue américain qui a introduit l’optimal matching dans les sciences scientifiques ou des séquences de pas de danses traditionnelles.

En France, les premiers travaux utilisant l’appariement optimal sont ceux de Claire Lemercier3 sur les carrières des membres des institutions consulaires parisiennes au xixe siècle (Lemercier, 2005), et de Laurent Lesnard4 sur les emplois du temps (Lesnard, 2008). Mais dès les années 1980, les chercheurs du Céreq construisaient des typologies de trajectoires d’insertion à l’aide des méthodes d’analyse des données « à la française » (analyse des correspondances, etc.)5. Au final, on dénombre maintenant plus d’une centaine d’articles de sciences sociales contenant ou discutant des techniques empruntées à l’analyse de séquences.

Pour une présentation des différentes méthodes d’analyse de séquences disponibles et de leur mise en oeuvre pratique, il existe un petit manuel en français, publié en 2011 dernière aux éditions du Ceped (collection « Les clefs pour »6) et disponible en pdf7 (Robette, 2011). De plus, un article récemment publié dans le Bulletin de Méthodologie Sociologique compare de manière systématique les résultats obtenus par les principales méthodes d’analyse de séquences (Robette & Bry, 2012). La conclusion en est qu’avec des données empiriques aussi structurées que celles que l’on utilise en sciences sociales, l’approche est robuste, c’est-à-dire qu’un changement de méthode aura peu d’influence sur les principaux résultats. Cependant, l’article tente aussi de décrire les spécificités de chaque méthode et les différences marginales qu’elles font apparaître, afin de permettre aux chercheurs de mieux adapter leurs choix méthodologiques à leur question de recherche.

Afin d’illustrer la démarche de l’analyse de séquences, nous allons procéder ici à la description « pas à pas » d’un corpus de carrières professionnelles, issues de l’enquête Biographies et entourage (Ined, 2000)8. Et pour ce faire, on va utiliser le logiciel R, qui propose la solution actuellement la plus complète et la plus puissante en matière d’analyse de séquences. Les méthodes d’analyse de séquences par analyses factorielles ou de correspondances ne nécessitent pas de logiciel spécifique : tous les logiciels de statistiques généralistes peuvent être utilisés (SAS, SPSS, Stata, R, etc.). En revanche, il n’existe pas de fonctions pour l’appariement optimal dans SAS ou SPSS. Certains logiciels gratuits implémentent l’appariement optimal (comme Chesa9 ou TDA10) mais il faut alors recourir à d’autres programmes pour dérouler l’ensemble de l’analyse (classification, représentation graphique). Stata propose le module sq11, qui dispose d’un éventail de fonctions intéressantes. Mais c’est R et le package TraMineR12, développé par des collègues de l’Université de Genève (Gabadinho et al, 2011), qui fournit la solution la plus complète et la plus puissante à ce jour : on y trouve l’appariement optimal mais aussi d’autres algorithmes alternatifs, ainsi que de nombreuses fonctions de description des séquences et de représentation graphique.

Installer TraMineR et récupérer les données

Tout d’abord, à quoi ressemblent nos données ? On a reconstruit à partir de l’enquête les carrières de 1000 hommes. Pour chacune, on connaît la position professionnelle chaque année, de l’âge de 14 ans jusqu’à 50 ans. Cette position est codée de la manière suivante : les codes 1 à 6 correspondent aux groupes socioprofessionnels de la nomenclature des PCS de l’INSEE 13 (agriculteurs exploitants ; artisans, commerçants et chefs d’entreprise ; cadres et professions intellectuelles supérieures ; professions intermédiaires ; employés ; ouvriers) ; on y a ajouté « études » (code 7), « inactivité » (code 8) et « service militaire » (code 9). Le fichier de données comporte une ligne par individu et une colonne par année : la variable csp1 correspond à la position à 14 ans, la variable csp2 à la position à 15 ans, etc. Par ailleurs, les enquêtés étant tous nés entre 1930 et 1950, on ajoute à notre base une variable « génération » à trois modalités, prenant les valeurs suivantes : 1=“1930-1938” ; 2=“1939-1945” ; 3=“1946-1950”. Au final, la base est constituée de 500 lignes et de 37 + 1 = 38 colonnes et se présente sous la forme d’un fichier texte au format csv (téléchargeable à http://larmarange.github.io/analyse-R/data/trajpro.csv).

Une fois R ouvert, on commence par installer les extensions nécessaires à ce programme (opération à ne réaliser que lors de leur première utilisation) et par les charger en mémoire. L’extension TraMineR propose de nombreuses fonctions pour l’analyse de séquences. L’extension cluster comprend un certain nombre de méthodes de classification automatique13.

install.packages(c("TraMineR"))
library(TraMineR)

TraMineR stable version 1.8-13 (Built: 2017-05-10)
Website: http://traminer.unige.ch
Please type 'citation("TraMineR")' for citation information.
library(cluster)

On importe ensuite les données, on recode la variable « génération » pour lui donner des étiquettes plus explicites. On jette également un coup d’oeil à la structure du tableau de données :

donnees <- read.csv("http://larmarange.github.io/analyse-R/data/trajpro.csv", 
  header = T)
donnees$generation <- factor(donnees$generation, labels = c("1930-38", 
  "1939-45", "1946-50"))
str(donnees)
'data.frame':   1000 obs. of  38 variables:
 $ csp1      : int  1 7 6 7 7 6 7 7 7 6 ...
 $ csp2      : int  1 7 6 7 7 6 7 7 6 6 ...
 $ csp3      : int  1 7 6 6 7 6 7 7 6 6 ...
 $ csp4      : int  1 7 6 6 7 6 7 7 6 6 ...
 $ csp5      : int  1 7 6 6 7 6 7 7 6 6 ...
 $ csp6      : int  1 7 6 6 7 6 9 7 6 6 ...
 $ csp7      : int  6 9 6 6 7 6 9 7 9 6 ...
 $ csp8      : int  6 9 9 6 7 6 9 7 4 6 ...
 $ csp9      : int  6 6 9 6 7 6 9 3 4 9 ...
 $ csp10     : int  6 6 9 6 7 6 4 3 4 9 ...
 $ csp11     : int  6 6 6 6 3 6 4 3 4 6 ...
 $ csp12     : int  6 6 6 6 3 6 4 3 4 6 ...
 $ csp13     : int  6 6 6 6 3 6 4 3 4 6 ...
 $ csp14     : int  6 4 6 6 3 6 4 3 4 6 ...
 $ csp15     : int  6 4 6 6 3 6 4 3 4 6 ...
 $ csp16     : int  6 4 6 6 3 6 6 3 4 6 ...
 $ csp17     : int  6 4 6 6 3 6 6 3 4 6 ...
 $ csp18     : int  6 4 6 6 3 6 6 3 4 6 ...
 $ csp19     : int  6 4 6 6 3 6 6 3 4 6 ...
 $ csp20     : int  6 4 6 6 3 6 6 3 4 6 ...
 $ csp21     : int  6 4 6 6 6 6 6 3 4 6 ...
 $ csp22     : int  6 4 6 6 6 6 6 3 4 4 ...
 $ csp23     : int  6 4 6 6 6 6 6 3 4 4 ...
 $ csp24     : int  6 6 6 6 5 6 6 3 4 4 ...
 $ csp25     : int  6 6 6 6 5 6 6 3 4 4 ...
 $ csp26     : int  6 6 6 6 5 6 6 3 4 4 ...
 $ csp27     : int  6 6 6 6 5 6 6 3 4 4 ...
 $ csp28     : int  6 6 6 6 5 6 6 3 4 4 ...
 $ csp29     : int  6 6 6 6 5 6 6 3 4 4 ...
 $ csp30     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp31     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp32     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp33     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp34     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp35     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp36     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ csp37     : int  4 6 6 6 5 6 6 3 4 4 ...
 $ generation: Factor w/ 3 levels "1930-38","1939-45",..: 2 1 1 3 2 3 1 1 2 1 ...

On a bien 1000 observations et 38 variables. On définit maintenant des labels pour les différents états qui composent les séquences et on crée un objet « séquence » avec seqdef :

labels <- c("agric", "acce", "cadr", "pint", "empl", 
  "ouvr", "etud", "inact", "smil")
seq <- seqdef(donnees[, 1:37], states = labels)
 [>] state coding:
       [alphabet]  [label]  [long label] 
     1  1           agric    agric
     2  2           acce     acce
     3  3           cadr     cadr
     4  4           pint     pint
     5  5           empl     empl
     6  6           ouvr     ouvr
     7  7           etud     etud
     8  8           inact    inact
     9  9           smil     smil
 [>] 1000 sequences in the data set
 [>] min/max sequence length: 37/37

Appariement optimal et classification

Ces étapes préalables achevées, on peut comparer les séquences en calculant les dissimilarités entre paires de séquences. On va ici utiliser la méthode la plus répandue, l’appariement optimal (optimal matching). Cette méthode consiste, pour chaque paire de séquences, à compter le nombre minimal de modifications (substitutions, suppressions, insertions) qu’il faut faire subir à l’une des séquences pour obtenir l’autre. On peut considérer que chaque modification est équivalente, mais il est aussi possible de prendre en compte le fait que les « distances » entre les différents états n’ont pas toutes la même « valeur » (par exemple, la distance sociale entre emploi à temps plein et chômage est plus grande qu’entre emploi à temps plein et emploi à temps partiel), en assignant aux différentes modifications des « coûts » distincts. Dans notre exemple, on va créer avec seqsubm une « matrice des coûts de substitution » dans laquelle tous les coûts sont constants et égaux à 214 :

couts <- seqsubm(seq, method = "CONSTANT", cval = 2)
 [>] creating 9x9 substitution-cost matrix using 2 as constant value

Ensuite, on calcule la matrice de distances entre les séquences (i.e contenant les « dissimilarités » entre les séquences) avec seqdist, avec un coût d’insertion/suppression (indel) que l’on fixe ici à 1,1 :

seq.om <- seqdist(seq, method = "OM", indel = 1.1, 
  sm = couts)
 [>] 1000 sequences with 9 distinct events/states
 [>] 818 distinct sequences
 [>] min/max sequence length: 37/37
 [>] computing distances using OM metric
 [>] total time: 1.63 secs

Cette matrice des distances ou des dissimilarités entre séquences peut ensuite être utilisée pour une classification ascendante hiérarchique (CAH), qui permet de regrouper les séquences en un certain nombre de « classes » en fonction de leur proximité :

seq.agnes <- agnes(as.dist(seq.om), method = "ward", 
  keep.diss = FALSE)

Avec la fonction plot, il est possible de tracer l’arbre de la classification (dendrogramme).

plot(as.dendrogram(seq.agnes), leaflab = "none")
Dendrogramme de la classification des séquences

De même, on peut représenter les sauts d’inertie.

plot(sort(seq.agnes$height, decreasing = TRUE)[1:20], 
  type = "s", xlab = "nb de classes", ylab = "inertie")
Sauts d’inertie de la classification des séquences

L’observation, sur ce dendogramme ou sur la courbe des sauts d’inertie, des sauts d’inertie des dernières étapes de la classification peut servir de guide pour déterminer le nombre de classes que l’on va retenir pour la suite des analyses. Une première inflexion dans la courbe des sauts d’inertie apparaît au niveau d’une partition en 5 classes. On voit aussi une seconde inflexion assez nette à 7 classes. Mais il faut garder en tête le fait que ces outils ne sont que des guides, le choix devant avant tout se faire après différents essais, en fonction de l’intérêt des résultats par rapport à la question de recherche et en arbitrant entre exhaustivité et parcimonie.

On fait ici le choix d’une partition en 5 classes :

nbcl <- 5
seq.part <- cutree(seq.agnes, nbcl)
seq.part <- factor(seq.part, labels = paste("classe", 
  1:nbcl, sep = "."))

Représentations graphiques

Pour se faire une première idée de la nature des classes de la typologie, il existe un certain nombre de représentations graphiques. Les chronogrammes (state distribution plots) présentent une série de coupes transversales : pour chaque âge, on a les proportions d’individus de la classe dans les différentes situations (agriculteur, étudiant, etc.). Ce graphique s’obtient avec seqdplot :

seqdplot(seq, group = seq.part, xtlab = 14:50, border = NA, 
  withlegend = T)
Chronogrammes

Chacune des classes semble caractérisée par un groupe professionnel principal : profession intermédiaire pour la classe 1, ouvrier pour la 2, employé pour la 3, cadre pour la 4 et indépendant pour la 5. Cependant, on aperçoit aussi des « couches » d’autres couleurs, indiquant que l’ensemble des carrières ne sont probablement pas stables.

Les « tapis » (index plots), obtenus avec seqiplot, permettent de mieux visualiser la dimension individuelle des séquences. Chaque segment horizontal représente une séquence, découpée en sous-segments correspondant aux aux différents états successifs qui composent la séquence.

seqiplot(seq, group = seq.part, xtlab = 14:50, tlim = 0, 
  space = 0, border = NA, withlegend = T, yaxis = FALSE)
Tapis des séquences triés

Il est possible de trier les séquences pour rendre les tapis plus lisibles (on trie ici par multidimensional scaling à l’aide de la fonction cmdscale).

ordre <- cmdscale(as.dist(seq.om), k = 1)
seqiplot(seq, group = seq.part, sortv = ordre, xtlab = 14:50, 
  tlim = 0, space = 0, border = NA, withlegend = T, 
  yaxis = FALSE)
Tapis des séquences triés par multidimensional scaling

On voit mieux apparaître ainsi l’hétérogénéité de certaines classes. Les classes 1, 3 et 4, par exemple, semblent regrouper des carrières relativement stables (respectivement de professions intermédiaires, d’employés et de cadres) et des carrières plus « mobiles » commencées comme ouvrier (classes 1 et 3, en orange) ou comme profession intermédiaire (classe 4, en rouge). De même, la majorité des membres de la dernière classe commencent leur carrière dans un groupe professionnel distinct de celui qu’ils occuperont par la suite (indépendants). Ces distinctions apparaissent d’ailleurs si on relance le programme avec un nombre plus élevé de classes (en remplaçant le 5 de la ligne nbcl <- 5 par 7, seconde inflexion de la courbe des sauts d’inertie, et en exécutant de nouveau le programme à partir de cette ligne) : les stables et les mobiles se trouvent alors dans des classes distinctes.

Le package JLutils, disponible sur GitHub, propose une fonction seq_heatmap permettant de représenter le tapis de l’ensemble des séquences selon l’ordre du dendrogramme.

Pour installer JLutils, on aura recours au package devtools et à sa fonction install_github :

library(devtools)
install_github("larmarange/JLutils")

On peut ensuite générer le graphique ainsi :

library(JLutils)
Loading required package: ggplot2
Loading required package: plyr
seq_heatmap(seq, seq.agnes, labCol = 14:50)
Tapis des séquences trié selon le dendrogramme

La distance moyenne des séquences d’une classe au centre de cette classe, obtenue avec disscenter, permet de mesurer plus précisément l’homogénéité des classes :

round(aggregate(disscenter(as.dist(seq.om), group = seq.part), 
  list(seq.part), mean)[, -1], 1)
[1] 13.1  8.9 15.6  9.7 16.5

Cela nous confirme que les classes 1, 3 et 5 sont nettement plus hétérogènes que les autres, alors que la classe 2 est la plus homogène.

D’autres représentations graphiques existent pour poursuivre l’examen de la typologie. On peut visualiser les 10 séquences les plus fréquentes de chaque classe avec seqfplot.

seqfplot(seq, group = seq.part, withlegend = T)
Séquences les plus fréquentes de chaque classe

On peut aussi visualiser avec seqmsplot l’état modal (celui qui correspond au plus grand nombre de séquences de la classe) à chaque âge.

seqmsplot(seq, group = seq.part, xtlab = 14:50, withlegend = T, 
  title = "classe")
Statut modal à chaque âge

On peut également représenter avec seqmtplot les durées moyennes passées dans les différents états.

seqmtplot(seq, group = seq.part, withlegend = T)
Durée moyenne dans chaque statut

Enfin, l’entropie transversale décrit l’évolution de l’homogénéité de la classe. Pour un âge donné, une entropie proche de 0 signifie que tous les individus de la classe (ou presque) sont dans la même situation. À l’inverse, l’entropie est de 1 si les individus sont dispersés dans toutes les situations. Ce type de graphique produit par seqHtplot peut être pratique pour localiser les moments de transition, l’insertion professionnelle ou une mobilité sociale ascendante.

seqHtplot(seq, group = seq.part, xtlab = 14:50, withlegend = T)
Entropie transversale

On souhaite maintenant connaître la distribution de la typologie (en effectifs et en pourcentages) :

library(questionr)
freq(seq.part)
           n    % val%
classe.1 280 28.0 28.0
classe.2 199 19.9 19.9
classe.3 114 11.4 11.4
classe.4 341 34.1 34.1
classe.5  66  6.6  6.6

On poursuit ensuite la description des classes en croisant la typologie avec la variable generation :

cprop(table(seq.part, donnees$generation))
          
seq.part   1930-38 1939-45 1946-50 Ensemble
  classe.1  25.6    27.1    31.0    28.0   
  classe.2  20.9    20.0    18.9    19.9   
  classe.3   7.9    13.6    12.9    11.4   
  classe.4  38.2    31.9    32.1    34.1   
  classe.5   7.4     7.5     5.2     6.6   
  Total    100.0   100.0   100.0   100.0   
chisq.test(table(seq.part, donnees$generation))

    Pearson's Chi-squared test

data:  table(seq.part, donnees$generation)
X-squared = 12.032, df = 8, p-value = 0.1498

Le lien entre le fait d’avoir un certain type de carrières et la cohorte de naissance est significatif à un seuil de 15 %. On constate par exemple l’augmentation continue de la proportion de carrières de type « professions intermédiaires » (classe 1) et, entre les deux cohortes les plus anciennes, l’augmentation de la part des carrières de type « employés » (classe 3) et la baisse de la part des carrières de type « cadres » (classe 4).

Bien d’autres analyses sont envisageables : croiser la typologie avec d’autres variables (origine sociale, etc.), construire l’espace des carrières possibles, étudier les interactions entre trajectoires familiales et professionnelles, analyser la variance des dissimilarités entre séquences en fonction de plusieurs variables « explicatives15 »…

Mais l’exemple proposé est sans doute bien suffisant pour une première introduction !

Bibliographie


  1. Pour une analyse des conditions sociales de la diffusion de l’analyse de séquences dans le champ des sciences sociales, voir Robette, 2012.

  2. http://home.uchicago.edu/~aabbott/

  3. http://lemercier.ouvaton.org/document.php?id=62

  4. http://laurent.lesnard.free.fr/article.php3?id_article=22

  5. Voir par exemple l’article d’Yvette Grelet (2002).

  6. http://www.ceped.org/?rubrique57

  7. http://nicolas.robette.free.fr/Docs/Robette2011_Manuel_TypoTraj.pdf

  8. Pour une analyse plus poussée de ces données, avec deux méthodes différentes, voir Robette & Thibault, 2008. Pour une présentation de l’enquête, voir Lelièvre & Vivier, 2001.

  9. http://home.fsw.vu.nl/ch.elzinga/

  10. http://steinhaus.stat.ruhr-uni-bochum.de/tda.html

  11. http://www.stata-journal.com/article.html?article=st0111

  12. http://mephisto.unige.ch/traminer/

  13. Pour une présentation plus détaillée, voir le chapitre sur la classification ascendante hiérarchique (CAH).

  14. Le fonctionnement de l’algorithme d’appariement optimal — et notamment le choix des coûts — est décrit dans le chapitre 9 du manuel de TraMineR (http://mephisto.unige.ch/pub/TraMineR/doc/TraMineR-Users-Guide.pdf).

  15. L’articulation entre méthodes « descriptives » et méthodes « explicatives » est un prolongement possible de l’analyse de séquences. Cependant, l’analyse de séquences était envisagée par Abbott comme une alternative à la sociologie quantitative mainstream, i.e le « paradigme des variables » et ses hypothèses implicites souvent difficilement tenables (Abbott, 2001). Une bonne description solidement fondée théoriquement vaut bien des « modèles explicatifs » (Savage, 2009).