<- data.table(
dtId id = "Françoise", # identifiant unique (libre)
dateNaissance = anneeMois(aaaa = 1960, mm = 4), # avril 1960
sexe = "Femme",
ageMort = 86,
nbEnfant = 0,
dateLiq = anneeMois(aaaa = 2022, mm = 4) # avril 2022
)
1 Premiers pas
Pour simuler le comportement de long terme de la population active, Trajectoire en mode “population” nécessite l’usage de données soumises au secret statistique . Le calcul de pension pour des cas-types est, lui, indépendant de ces sources confidentielles.
Les données concernées sont: - EIC 2013 et 2017 - Appariement EIC - Pannel tous actifs 2013 et 2017 - EIR 2012 et 2016
Les autorisations d’accès sont données par le comité du secret statistique, qui se réunit quatre fois par an, sur présentation d’un projet motivé. Le calendrier des prochaines sessions est disponible ici mais il faut prévoir plusieurs mois pour un premier accès. Une copie de la demande doit être envoyée à drees-sol@sante.gouv.fr et les bases de données ci-dessus doivent toute être référencées, avec leur millésime.
Sur réponse postive, le Centre d’Accès Sécurisé aux Données (CASD) vous accompagnera pour accéder aux données. L’accès via le CASD est payant et Trajectoire nécessite au minimum 32 Go de mémoire vive pour une exécution sur l’EIR complet (et plutôt 64 Go pour travailler confortablement). Au 25/09/2023, une telle configuration pour un seul utilisateur coûtait 37€/mois pour le boitier d’accès sécurisé et 253+466=719€/mois pour la location de la machine virtuelle (source ; les prix sont fortement dégressifs après le premier utilisateur).
Nous travaillons an parallèle à construire des données synthétiques afin de pouvoir tester les fonctionalités de Trajectoire sans avoir accès à ces données confidentielles. Trajectoire offre en outre la possibilité de travailler sur un échantillon de l’EIC pour permettre l’usage de configurations matérielles plus faibles, sans perte notable de qualité (voir étape 2.30 pour une explication et section 1 pour un exemple).
1.1 Installation
L’installation de Trajectoire se fait soit depuis le Gitlab public de la Drees, soit depuis une copie locale sur le CASD. Le paquet trajectoire
n’est pas sur le CRAN.
Pour l’installation de la version de développement voir la section contribuer.
::install_gitlab("https://git.drees.fr/drees_code_public/modeles/trajectoire") devtools
#TODO: choisir emplacement avec CASD
install.packages(
"C:/Users/Public/Documents/trajectoire_0.1.tar.gz",
type = "source"
)
Ensuite, Trajectoire peut être utilisé en chargeant le package normalement :
library(trajectoire)
1.2 Initialisation d’un projet
Un projet Trajectoire commence par l’appel à la fonction init()
. Cette fonction crée :
- un script R reprenant les éléments de cette introduction ;
- un fichier de configuration au format YAML
- un dossier
_cache
pour sauvegarder les résultats intermédiaires des calculs
De plus, la fonction init()
exécute les premières étapes de Trajectoire. Indépendantes des carrières, ces étapes n’ont pas vocation à être réexécutées fréquemment.
1.3 Utilisation en mode cas-type
Commençons avec un exemple et modélisons la carrières et les droits d’une personne salariée du privé, en faisant l’hypothèse d’une carrière entièrement au SMIC.
1.3.1 Préparation
Dans ce cas simple, deux bases sont à remplir :
- les données à caractère individuel dans
dtId
; - et les données de carrière dans
dtIdAnEtat
.
Commençons par les données individuelles : identifiant, date de naissance, sexe, âge de décès, nombre d’enfants et date de liquidation des droits à la retraite. Les dates sont supposées connues au mois près.
id
est un identifiant individuel unique arbitrairement au choix de l’utilisateur, par ex."salariée du privé au SMIC"
,"59093xvf4"
,"cas-type 3"
ou encore comme ici"Françoise"
dateLiq
, la date de liquidation des droits à la retraite, peut être renseignée ici lorsque celle-ci est la même dans toutes les caisses ; c’est le cas ici puisque la personne ne cotise qu’au régime général
Pour la carrière, on renseigne les informations année par année. Le SMIC étant mis à jour au premier janvier de chaque année, on fera commencer la carrière de notre salariée au premier janvier 1980 et terminer le 31 décembre 2022.
<- data.table(
dtIdAnEtat id = "Françoise",
annee = 1980:2022, # de 1980 à 2022 (date de liquidation)
etatTravail = "Salarie du prive non cadre", # voir ci-dessous
remuneration = serieSmic(1980, 2022)
)
Le revenu est le revenu annuel, même pour la dernière année1. La fonction utilitaire serieSmic
permet de récupérer le revenu annuel au SMIC pour les années sélectionnées2. L’état travaillé "Salarie du prive non cadre"
est un des états possibles dans la modélisation de Trajectoire. Voir ici pour la liste des états possibles.
1.3.2 Calcul
La fonction calculePension()
calcule les droits à la retraite sur la base de la carrière déclarée et des caracteristiques de la personne. calculePension()
, comme la fonction lancerModele(..., mode='cas-type')
qu’elle enveloppe, exécutent une à une les étapes de la modélisation.
<- calculePension(dtId = dtId, dtIdAnEtat = dtIdAnEtat) resultats
Les étapes du calcul des pensions occupent la plus grande partie de la présente documentation. La liste des étapes exécutées en mode “cas-types” par est accessibles ainsi :
==TRUE ] etapes[ dansCasType
1.3.3 Résultats
Une fois les calculs effectués, il est recommandé de “déplier” les résultats dans l’environnement de travail. Cela permet d’écrire par exemple simplement dtIdCaisse
au lieu de resultats$dtIdCaisse
.
list2env(resultats, envir = globalenv())
Les résultats sont organisés dans plusieurs tables, présentées ci-dessous. Par mi elles, on retiendra notamment :
dtIdPensionnes
pour les données par pensionné.es (les personnes sans pension sont donc exclues)dtIdCaisse
pour les données par régime (deux dans notre exemple, le régime général et le régime complémentaire Agirc-Arco ; les pensions sont données brutes à la date de liquidation)dtIdAnCaissePension
pour les chroniques de pensions, c’est-à-dire les pensions touchées mensuellement jusqu’à la mort et où chaque ligne s’interprète ainsi : “L’annéeannee
, pendantduree
mois, la personne a touché une pension mensuelle depension
euros.”
Les autres tables contiennent des informations sur les salaires de référence pour les régimes en annuités (en euros courants à la date de liquidation ; dtIdCaisseSalaireReference
), les données des régimes de base (par opposition aux régimes complémentaires ; dtIdCaisseBase
) ou les régimes avec modulation temporaire des pensions (dtIdCaisseModulationTemporaire
). dtId
reprend les données fournies en entrée mais contient également une colonne type
qui permet d’identifier les personnes non inclues dans les autres tables (personnes décédées avant l’ouverture de leurs droits, personnes n’ayant droit à aucune pension, etc.).
La fusion des régimes Agirc et Arrco à partir de 2019 est prise en compte, et tout se passe comme si l’individu avait toujours cotisé au régime unifié Agirc-Arrco.
Les tables dtIdAnCaisse
, pour les régimes de base, et dtIdAnCaisseComplementaire
, pour les régimes complémentaires, contiennent des informations annuelles par caisse sur les droits acquis au cours de la carrière.
1.3.4 Personne cotisant dans plusieurs caisses
Pour une personne ayant cotisé dans plusieurs caisses au cours de sa carrière, on spécifie simplement la caisse de cotisation. Prenons l’exemple d’un homme ayant travaillé dans le public, tout d’abord comme contractuel, puis comme fonctionnaire d’administration centrale.
<- data.table(
dtId id = "Grégoire",
dateNaissance = anneeMois(aaaa = 1958, mm = 1), # janvier 1958
sexe = "Homme",
ageMort = 78,
nbEnfant = 3,
dateLiq = anneeMois(aaaa = 2021, mm = 9) # septembre 2021
)
Par simplicité, on suppose que cette personne a également eu une carrière au SMIC.
<- data.table(
dtIdAnEtat id = "Grégoire",
annee = 1978:2021,
etatTravail = c(
rep("Contractuel de la FP", 15), # 15 années contractuel de la fonction publique
rep("FPE", 29) # 29 années fonction publique d'État
), remuneration = serieSmic(1978, 2021)
)
Par contre, dans le public, une part de la rémunération est assurée sous forme de primes, qui rentrent dans le calcul de la pension complémentaire (RAFP), mais pas de la pension de base (SRE). Il est donc nécessaire de préciser le montant de ces primes. Supposons que le taux de prime soit de 5 % :
<- data.table(
dtIdAnCaisseFonctionnaire id = "Grégoire",
annee = (1978+15):2021, # uniquement pour les années dans la fonction publique
caisse = "SRE",
primes = 0.05*serieSMPT(1978+15,2021)
)
Le calcule des pensions utilise cette information spécifique aux fonctionnaires :
<- calculePension(
resultats dtId = dtId, dtIdAnEtat = dtIdAnEtat,
dtIdAnCaisseFonctionnaire = dtIdAnCaisseFonctionnaire # nouveau !
)
Les résultats respectent le même format que précédemment. On pourra vérifier que, par exemple dans dtIdAnCaisseComplementaire
, Grégoire cotise bien à l’Ircantec dans un premier temps (caisse complémentaire des contractuels de la fonction publique) puis au RAFP ensuite (complémentaire de la fonction publique).
list2env(resultats, envir = globalenv())
<environment: R_GlobalEnv>
1.3.5 Modéliser plusieurs cas simultanément
Pour modéliser plusieurs cas-types, qu’il s’agisse de personnes distinctes ou de variantes concernant la même personne, il est possible de présenter l’ensemble des données en une seule fois. Prenons l’exemple d’une femme dont nous souhaiterions savoir comment le nombre d’enfant influence la pension.
# Ce tableau comporte 4 lignes, donc 4 cas-types :
<- data.table(
dtId id = c("Sans enfant", "1 enfant", "2 enfants", "3 enfants"), # 4 valeurs
dateNaissance = anneeMois(aaaa = 1956, mm = 8), # août 1956
sexe = "Femme",
ageMort = 85,
nbEnfant = c(0, 1, 2, 3), # 4 valeurs
dateLiq = anneeMois(aaaa = 2024, mm = 4) # janvier 2024
)
On suppose que la carrière de cette personne est identique sans ou avec un enfant, mais qu’elle diminue son temps de travail à 90% à partir du premier enfant, puis à 80% à partir du troisième. Supposons que cette femme est une cadre du privé gagnant 2,5 fois le SMIC3.
<- rbind(
dtIdAnEtat data.table(
id = "Sans enfant",
annee = 1956:2024,
etatTravail = "Salarie du prive cadre",
remuneration = 2.5*serieSmic(1956, 2024)
),data.table(
id = "1 enfant",
annee = 1956:2024,
etatTravail = "Salarie du prive cadre",
remuneration = 2.5*serieSmic(1956, 2024)
),data.table(
id = "2 enfants",
annee = 1956:2024,
etatTravail = "Salarie du prive cadre",
remuneration = c(
2.5*serieSmic(1956, 1956+30-1),
0.9*2.5*serieSmic(1956+30, 2024) # 2e enfant à 30 ans
)
),data.table(
id = "3 enfants",
annee = 1956:2024,
etatTravail = "Salarie du prive cadre",
remuneration = c(
2.5*serieSmic(1956, 1956+30-1),
0.9*2.5*serieSmic(1956+30, 1956+32-1),
0.8*2.5*serieSmic(1956+32, 2024) # 3e enfant à 32 ans
)
) )
On procède ensuite comme précédemment :
<- calculePension(dtId = dtId, dtIdAnEtat = dtIdAnEtat)
resultats list2env(resultats, envir = globalenv())
<environment: R_GlobalEnv>
On peut maintenant comparer le résultats, par exemple ici les pensions mensuelles moyennes :
|>
dtIdAnCaissePension ::group_by(id, annee) |>
dplyr::summarise(pension=sum(pension*duree)/sum(duree)) |>
dplyr::mutate(id = factor(id, levels=dtId$id)) |>
dplyrggplot(aes(x=annee,y=pension)) +
geom_line(
aes(colour=id, linetype=id), size=1,
position=position_jitter(width=0, height=2) # pour voir la ligne du dessous
+
) scale_y_continuous(labels = scales::label_number(suffix = " €")) +
scale_linetype_manual(
values = c(
"Sans enfant" = "solid",
"1 enfant" = "longdash",
"2 enfants" = "dashed",
"3 enfants" = "dotted"
)+
) labs(
x = NULL, y = NULL, title="Pension mensuelle moyenne ", colour=NULL, linetype=NULL) +
theme_minimal()
1.4 Utilisation en mode population
Pour simuler le comportement de long terme de la population active, Trajectoire en mode “population” nécessite l’usage de données soumises au secret statistique . Le calcul de pension pour des cas-types est, lui, indépendant de ces sources confidentielles.
Les données concernées sont: - EIC 2013 et 2017 - Appariement EIC - Pannel tous actifs 2013 et 2017 - EIR 2012 et 2016
Les autorisations d’accès sont données par le comité du secret statistique, qui se réunit quatre fois par an, sur présentation d’un projet motivé. Le calendrier des prochaines sessions est disponible ici mais il faut prévoir plusieurs mois pour un premier accès. Une copie de la demande doit être envoyée à drees-sol@sante.gouv.fr et les bases de données ci-dessus doivent toute être référencées, avec leur millésime.
Sur réponse postive, le Centre d’Accès Sécurisé aux Données (CASD) vous accompagnera pour accéder aux données. L’accès via le CASD est payant et Trajectoire nécessite au minimum 32 Go de mémoire vive pour une exécution sur l’EIR complet (et plutôt 64 Go pour travailler confortablement). Au 25/09/2023, une telle configuration pour un seul utilisateur coûtait 37€/mois pour le boitier d’accès sécurisé et 253+466=719€/mois pour la location de la machine virtuelle (source ; les prix sont fortement dégressifs après le premier utilisateur).
Nous travaillons an parallèle à construire des données synthétiques afin de pouvoir tester les fonctionalités de Trajectoire sans avoir accès à ces données confidentielles. Trajectoire offre en outre la possibilité de travailler sur un échantillon de l’EIC pour permettre l’usage de configurations matérielles plus faibles, sans perte notable de qualité (voir étape 2.30 pour une explication et section 1 pour un exemple).
1.4.1 Lancer une simulation
Trajectoire a comme situation de référence la législation courante, à quelques simplifications près. Pour lancer ce “scénario de référence”, utilisons la fonction lancerModele()
. Sur le CASD, certaines étapes ne sont pas effectuées par manque d’une connexion Internet. Les données correspondantes sont récupérées depuis le package lui-même mais peuvent ne pas être à jour.
Attention! Le temps d’exécution de Trajectoire se compte en demi-heures ! On peut réduire la finesse du modèle avec tauxReduction=...
, ce qui divise d’autant le nombre de trajectoires simulées.
lancerModele(tauxReduction = 10)
1.4.2 Principe des variantes
Pour créer une variante simple, l’idée est d’intervenir au niveau d’une ou plusieurs étapes de Trajectoire. Concevoir une variante constructive, qui implémente de nouveaux dispositifs, demande une connaissance relativement fine du système des retraites et de son implémentation dans Trajectoire. Désactiver un dispositif existant pour en mesurer l’impact est souvent plus facile.
Pour concevoir une variante, il faut : - identifier les étapes concernées, soit via la documentation, soit via la table etapes
- identifier si les modifications souhaitées suppriment, remplacent ou annulent les étapes identifiées - écrire les fonctions qui effectuent ces changements ; dans certains cas simples, il suffit de changer les options des fonctions existantes - dans un script, utiliser lancerModele(premiereEtape=..., derniereEtape=..., scenario=<nom de la variante>)
pour lancer les séries d’étapes non modifiées, et exécuter les étapes modifiées via des scripts
Dans les sauvegardes, Trajectoire crée un embranchement à parti de la première étape relancée avec un nouveau nom de scénario. Les résultats du scénario central sont alors réutilisés lorsque des étapes plus tardives font appel aux résultats des premièrs étapes. Par exemple, une variante sur la durée de cotisation permettant d’atteindre le taux plein n’a de conséquence qu’en fin de modélisation. Aussi, cette variante réutilisera la modélisation des carrières du scénario central. Pour cette raison, le tirage des aléas pour la modélisation est cenrtralisée en début de modélisation, pour que les individus restent comparables d’un scénario à l’autre.
Des exemples simples sont donnés ci-dessous. Nous contacter pour des variantes plus complexes. En particulier, un mécanisme non documenté de “cascade” de scénarios permet de représenter les “couches” successives d’une variante complexe.
1.4.3 Inventer une variante législative simple
Imaginons que nous souhaitions évaluer le dimensionnement des dispositifs de prise en compte des carrières longues. Qui sont les personnes bénéficiaires et quel est le coût pour la collectivité ?
Avec Trajectoire, nous pouvons répondre à cette question en imaginant un monde contre-factuel sans prise en charge des carrrières longues, puis en comparant cette variante avec la simulation standard.
Voici comment procéder. Tout d’abord on définit le nom de notre variante :
# nom de la variante
<- "contreFactuelSansCarrieresLongues" varianteLegislative
Ensuite on vient supprimer l’effet du dispositif qui nous intéresse. Ici, on repère l’étape qui détermine les carrières longues selon la législation puis, à la sortie de cette étape, on supprime toutes les personnes identifiées comme ayant vécu une longuer carrière. On relance ensuite le modèle à partir de cette étape. Le début du modèle, lui, reste identique au scénario central et n’est donc pas réexécuté !
# identifiant de l'étapes où intervenir
<- etapes[fonction=='carrieresLongues', id]
idCarrieresLongues
# à la *sortie* de cette étape, on a une table
# qui recense toutes les personnes éligibles au dispositifs
# de prise en compte desw carrières longues
charge(
dtIdRacl,# par défaut, charge() récupère les tables existant *en entrée*
# d'où l'utilisation de idCarrieresLongues + 1 pour les tables *en sortie*
etape = idCarrieresLongues + 1,
# tauxReduction = 10 est obligatoire pour savoir dans quel dossier
# aller chercher la table (même valeur que dans lancerModele() ci-dessus)
tauxReduction = 10
)
# on vide complètement cette table
# afin de supprimer toutes les personnes identifiées comme 'carrière longue'
# et on la sauvegarde un nouvel embranchement (scenario = varianteLegislative),
<- dtIdRacl[FALSE]
dtIdRacl sauvegarde(
dtIdRacl,etape = idCarrieresLongues,
scenario = varianteLegislative,
tauxReduction = 10
)
# enfin on reprend le modèle à partir de cette étape
# en restant sur le nouvel embranchement / scénario
lancerModele(
premiereEtape = idCarrieresLongues+1,
scenario = varianteLegislative,
tauxReduction = 10
)
Ensuite on peut utiliser la fonction lancerVariancesVsReference()
pour analyser les résultats de la simulation au regard de la simulation de référence. Par défaut, ce code produit un document au format HTML qui est par défaut placé dans un dossier sorties
à la racine du projet.
lancerVariantesVsReference(
listeNomsVariantes = varianteLegislative,
tauxReduction = 10
)
charge(paramModele)
$anneeEic paramModele
Notons que le “présent” de Trajectoire est la dernière année observéee de l’EIC (paramModele$anneeEic
) et que par défaut il n’existe pas de date d’application d’une réforme. Toute réforme décrite dans Trajectoire s’applique sans délai à partir de cette date. Dans notre exemple, cela signifie que les dispositifs de carrière longue sont supprimés à partir de paramModele$anneeEic
.
En revanche, les variantes ciblant des générations particulières, pour autant que ces générations soient en 2017 encore suffisamment loin de l’âge de la retraite, sont structurellement immunisée, puisqu’elles s’appliquent au fur et à mesure que ces générations arrivent à l’âge de la retraite.
La plupart des événements et comportements modélisés dans Trajectoire restent fixes, indépendemment de la législation liée aux retraites. En particulier, les trajectoires sur le marché du travail restent les mêmes dans la simulation standard et dans la simulation contre-factuelle ; seule change l’éventuelle date du départ à la retraite. (Rappelons que les individus possèdent une trajectoire professionnelle virtuelle jusqu’à 70 ans justement pout permettre des telles comparaisons à carrière fixée.) Par ailleurs, la date départ est obtenue par un calcul probabiliste à la date \(t\), sans anticipation de législation. Pour revenir à notre exemple, cela signifie que dans Trajectoire, les personnes de 18 ans font leur arbitrage étudier/travailler de façon indépendante de l’existence d’un dispositifs de prise en charge des carrières longues. En revanche, une fois à la fin de leur carrière, la date exacte de leur départ est recalculée dans le monde “sans carrières longues” puisque les conditions particulières (date d’ouverture des droits, montant des pensions) ont changé.
1.4.4 Exécuter une variante macroéconomique simple
Quel est l’impact des hypothèses de croissance sur la santé du système de retraite ? Une hausse ponctuelle du chômage se répercute-t-elle durablement dans le niveau des retraites ? Quels sont les perdants et les gagnants d’une moindre inflation ? Trajectoire permet de simuler ce type de scénarios.
Dans Trajectoire, la croissance économique est captée via la croissance des revenus du travail, ou salaire moyen par tête (SMPT), en supposant un partage constant de la croissance entre capital et travail. La croissance future est anticipée dans des variantes du COR, desquelles Trajectoire est tributaire. Ces variantes consistent généralement en une phase de moyen terme reprenant les projections du plan de stabilité du ministère du budget, suivi d’une transition vers des projections de long terme stables.
Le taux de chômage impacte les effectifs de cotisants, ici aussi contraints par les scénarios de prévision du COR. L’inflation, elle, peut être librement choisie dans la mesure où son impact se limite à la revalorisations de certains seuils et prestations.
<- "chomageFaibleCroissanceFaible"
varianteEconomique charge(paramModele)
$hypChomage <- "Chô 5%"
paramModele# cette variante doit exister dans les fichiers d'hypothèses du COR
# system.file("extdata", "cor", paramModele$fichierCorCotisant, package='trajectoire')
$hypSmpt <- 0.7
paramModele# cette variante doit exister dans les fichiers d'hypothèses du COR
# system.file("extdata", "cor", paramModele$fichierCorSalairePrix, package='trajectoire')
sauvegarde(paramModele, scenario = varianteEconomique, etape="00.00")
lancerModele(
# on relance depuis la première étape à partir de laquelles ces
# hypothèses ont des conséquences
premiereEtape = etapes[fonction %in% c(
"prepareCibles", # effectifs par secteurs, dépend du chômage
"choixHypSmptCor" # choix de l'hyp de salaire
min(id)],
), scenario = varianteEconomique,
tauxReduction = 10
)
1.4.4.1 Absence de rétroaction macroéconomique
Trajectoire n’est pas un modèle macroéconomique, et à ce titre nous ne vérifions pas la cohérence des projections ; cette vérification incombe dès lors à l’utilisateur. Trajectoire ne connaît aucune notion de “demande de travail”, et le nombre de cotisants est fixé uniquement par les projections du Conseil d’orientation des retraites (COR), qui connaît une poignée de variantes démographiques et économiques. Ainsi, le taux de chômage n’influence que les cibles annuelles d’effectifs de cotisants. La croissance économique ne joue un rôle que via la croissance des salaires. Enfin, l’inflation ne rentre en compte que pour la revalorisation des pensions et des valeurs législatives de référence.
1.4.5 Imaginer une variante démographique simple
Combien de pensions devra-t-on verser lors d’un emballement de l’immigration ? Quelle soutenabilité fasse à une baisse de la fécondité ? De la même façon que les variantes économiques, les variantes démographiques les plus aisées à modéliser sont celles anticipées par le COR, et qui définissent les cibles annuelles de cotisants utilisées dans Trajectoire.
Dans le privé, ce salaire ne rentre pas en compte pour le calcul des meilleures années, et n’est utile que pour valider des trimestres.↩︎
On suppose en particulier que cette personne est trop riche pour bénéficier du dispositif d’AVPF (qui compenserait le temps partiel pour enfant par des salaires virtuels au SMIC) mais ne dépasse cependant pas les plafonds d’indemnité journalière de la Caisse Nationale d’Assurance Maladie pour indemniser les congés parentaux.↩︎