5  Lire un dictionnaire de données, les labels et les types

ImportantQuestion de départ

Si une colonne contient les valeurs 1, 2, 3, 98 et 99, comment savoir si elle représente une quantité, une catégorie ordonnée, « ne sait pas » ou un refus de répondre ?

5.1 Objectifs d’apprentissage

À la fin de ce chapitre, vous saurez :

  • distinguer nom de variable, label de variable, valeur et label de valeur ;
  • utiliser le questionnaire et le dictionnaire comme partie intégrante de l’analyse ;
  • distinguer type conceptuel, type de stockage et classe R ;
  • comprendre un objet haven_labelled sans le convertir trop tôt ;
  • inspecter les labels avec {labelled} et {haven} ;
  • reconnaître les codes spéciaux : « sans objet », « ne sait pas », « refus » ;
  • décider quand convertir une variable en facteur et quand conserver sa version codée ;
  • produire une première fiche de variables avant tout nettoyage.

5.2 Prérequis

Il faut savoir importer un fichier, utiliser class(), str(), glimpse() et count().

5.3 Une colonne n’est pas auto-documentée

Le fichier de données peut contenir :

diplome
4
6
3
98
4
99

Sans documentation, plusieurs interprétations sont possibles. Le code 6 pourrait signifier « Bac+5 », une note sur 10, une catégorie de PCS ou autre chose. Les valeurs 98 et 99 peuvent être des réponses réelles, des codes spéciaux ou des erreurs.

C’est pourquoi l’analyse d’enquête repose sur un ensemble de documents :

  • le questionnaire ;
  • le dictionnaire de variables ou codebook ;
  • éventuellement le manuel d’enquête, les filtres, consignes aux enquêteurs et notes méthodologiques ;
  • le fichier de microdonnées lui-même.

Le chapitre 1 insistait sur ce point : le fichier n’est qu’une partie de l’enquête. Ici, nous transformons ce principe en routine de travail.

5.4 Les quatre éléments à ne pas confondre

Prenons la variable diplome du jeu EnquêteR.

5.4.1 Nom de variable

diplome

C’est le nom utilisé dans le code.

5.4.2 Label de variable

Niveau de diplôme le plus élevé obtenu

Il donne une formulation plus lisible et plus proche du questionnaire.

5.4.3 Valeur ou code

1, 2, 3, ..., 98, 99

C’est ce qui est stocké dans les lignes du fichier.

5.4.4 Label de valeur

1 = Sans diplôme
2 = Brevet / CEP
3 = CAP / BEP
...
98 = Ne sait pas
99 = Refus

Un format statistique comme Stata ou SPSS peut stocker ces associations directement avec la variable. Un CSV, lui, n’embarque généralement pas ce dictionnaire.

NoteÀ retenir

Le nom sert au code ; le label sert à la lecture ; le code est stocké ; le label de valeur explique le code. Les quatre informations peuvent coexister sans être interchangeables.

5.5 Le dictionnaire fourni avec le livre

Le fichier :

data/documentation/dictionnaire_variables.xlsx

contient trois feuilles :

  • Variables : description de chaque variable ;
  • Modalites : détail des codes et libellés ;
  • Anomalies pedagogiques : anomalies volontairement introduites dans le fichier brut.

Une version CSV de la feuille principale est également fournie :

Afficher le code R
dictionnaire <- readr::read_csv(
  "data/documentation/dictionnaire_variables.csv",
  show_col_types = FALSE
)

dplyr::glimpse(dictionnaire)
Rows: 36
Columns: 11
$ ordre           <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,…
$ variable        <chr> "id", "strate", "psu", "poids_base", "poids_final", "t…
$ libelle         <chr> "Identifiant pseudonymisé du répondant", "Strate d'éch…
$ section         <chr> "Métadonnées / plan", "Métadonnées / plan", "Métadonné…
$ type_conceptuel <chr> "Identifiant", "Plan d'enquête", "Plan d'enquête", "Po…
$ type_brut       <chr> "numérique", "numérique", "numérique", "numérique", "n…
$ modalites_codes <chr> NA, "1 = Métropoles ; 2 = Grandes villes ; 3 = Villes …
$ codes_speciaux  <chr> NA, NA, NA, NA, NA, NA, NA, "9 = Préfère ne pas répond…
$ univers         <chr> "Tous les répondants", "Tous les répondants", "Tous le…
$ role            <chr> "Identifiant", "Plan d'enquête", "Plan d'enquête", "Pl…
$ notes           <chr> NA, NA, NA, NA, NA, NA, NA, NA, "Champ théorique : 18-…

Quelques colonnes importantes :

  • variable : nom informatique ;
  • libelle : définition lisible ;
  • type_conceptuel : nature substantive ;
  • type_brut : représentation attendue dans le fichier brut ;
  • modalites_codes : codes documentés ;
  • codes_speciaux : non-réponse ou sans objet ;
  • univers : population à laquelle la question s’applique ;
  • role : variable d’analyse, de plan, identifiant, etc.

Cette dernière information, l’univers, est essentielle. Une absence de réponse à une question sur le télétravail n’a pas le même sens chez une personne en emploi et chez une personne retraitée.

5.6 Trois niveaux de « type »

5.6.1 Type conceptuel

Il correspond à la nature statistique ou substantive de la variable :

  • nominale ;
  • ordinale ;
  • quantitative discrète ;
  • quantitative continue ;
  • identifiant ;
  • poids ;
  • date ;
  • question à réponses multiples.

5.6.2 Type de stockage

Le fichier peut stocker une variable comme :

  • nombre entier ;
  • nombre décimal ;
  • texte ;
  • date ;
  • valeur + labels.

5.6.3 Classe R

Après import, R peut afficher :

numeric
character
factor
Date
haven_labelled
haven_labelled_spss

Ces niveaux doivent être mis en correspondance, mais ils ne sont pas identiques.

5.6.4 Exemple : sante

La question va de « très bonne » à « très mauvaise ». Conceptuellement, elle est ordinale. Dans le CSV, elle est stockée par des nombres. Dans un fichier Stata, elle peut être un vecteur numérique avec labels. Pour l’analyse, on peut décider de la convertir en facteur ordonné.

5.6.5 Exemple : id

id est numérique dans le fichier, mais conceptuellement c’est un identifiant. Une moyenne de id n’a aucune signification.

5.6.6 Exemple : poids_final

poids_final est numérique et doit rester numérique, mais il n’est pas une variable substantive : il intervient dans le plan d’analyse.

AvertissementErreur fréquente — confondre code et mesure

Le fait qu’une variable soit stockée sous forme numérique autorise certaines fonctions R, mais ne les rend pas scientifiquement pertinentes. La documentation précède le choix de la statistique.

5.7 Les objets haven_labelled

Lorsque {haven} importe un fichier Stata, SPSS ou SAS, les valeurs étiquetées sont souvent représentées par un vecteur haven_labelled (Wickham et al. 2026).

Afficher le code R
enquete_dta <- haven::read_dta("data/raw/enqueter_brut.dta")
class(enquete_dta$diplome)
[1] "haven_labelled" "vctrs_vctr"     "double"        

Un objet étiqueté conserve :

  • ses valeurs numériques ;
  • un attribut contenant les labels des valeurs ;
  • éventuellement un label de variable.

5.7.1 Inspecter les labels

Avec {labelled} (Larmarange 2026) :

Afficher le code R
labelled::var_label(enquete_dta$diplome)
[1] "Plus haut diplôme obtenu"
Afficher le code R
labelled::val_labels(enquete_dta$diplome)
   Sans diplôme      Brevet/CEP         CAP/BEP    Baccalauréat           Bac+2 
              1               2               3               4               5 
        Licence Master/doctorat     Ne sait pas           Refus 
              6               7              98              99 

Pour obtenir une vue plus large :

Afficher le code R
labelled::look_for(enquete_dta, "dipl")
 pos variable label                    col_type missing values             
 10  diplome  Plus haut diplôme obtenu dbl+lbl  0       [1] Sans diplôme   
                                                        [2] Brevet/CEP     
                                                        [3] CAP/BEP        
                                                        [4] Baccalauréat   
                                                        [5] Bac+2          
                                                        [6] Licence        
                                                        [7] Master/doctorat
                                                        [98] Ne sait pas   
                                                        [99] Refus         

look_for() est particulièrement utile dans les enquêtes comportant des centaines de colonnes : on peut rechercher un mot dans les noms et labels.

5.8 Pourquoi ne pas convertir toutes les variables immédiatement ?

Une stratégie tentante est :

enquete_dta |>
  mutate(across(where(haven::is.labelled), haven::as_factor))

Cette conversion peut être pratique pour une table exploratoire, mais l’appliquer automatiquement à toutes les colonnes peut masquer des distinctions importantes :

  • un code 98 = ne sait pas devient une modalité ordinaire ;
  • un score numérique étiqueté peut être transformé en facteur alors qu’il doit rester numérique ;
  • l’ordre substantiel d’une variable ordinale n’est pas nécessairement correctement défini ;
  • une catégorie de référence pour une régression peut être choisie sans réflexion ;
  • les valeurs brutes deviennent moins faciles à auditer.

Dans ce livre, nous conservons une copie brute et créons des variables d’analyse explicitement.

AstuceBon réflexe

Avant toute conversion globale, inspecter : le label, les codes, l’univers de la question et l’usage analytique prévu.

5.9 Convertir sélectivement en facteur

Pour une variable catégorielle dont les codes spéciaux ont déjà été traités :

Afficher le code R
diplome_facteur <- haven::as_factor(
  enquete_dta$diplome,
  levels = "labels"
)

Avec {labelled}, to_factor() fournit aussi des outils de conversion adaptés aux données étiquetées (Larmarange 2026).

Mais l’étape méthodologique importante reste : quelles modalités doit-on conserver et dans quel ordre ?

5.10 Variables nominales et ordinales

5.10.1 Nominale

Les modalités n’ont pas d’ordre naturel unique.

Exemples :

  • territoire ;
  • mode de collecte ;
  • situation familiale ;
  • sexe/genre lorsqu’il est utilisé comme variable nominale.

5.10.2 Ordinale

Les modalités possèdent un ordre substantiel, sans supposer que l’écart entre deux catégories successives est constant.

Exemples :

  • état de santé de « très bon » à « très mauvais » ;
  • fréquence d’usage d’Internet ;
  • confiance de « aucune » à « très forte ».

Dans R :

Afficher le code R
sante_demo <- factor(
  c("Bonne", "Moyenne", "Très bonne", "Mauvaise"),
  levels = c("Très mauvaise", "Mauvaise", "Moyenne", "Bonne", "Très bonne"),
  ordered = TRUE
)

sante_demo
[1] Bonne      Moyenne    Très bonne Mauvaise  
Levels: Très mauvaise < Mauvaise < Moyenne < Bonne < Très bonne

L’ordre doit être écrit explicitement lorsque le tri alphabétique ne correspond pas au sens de la variable.

5.11 Variables quantitatives discrètes et continues

5.11.1 Discrète

Un compte prend généralement des valeurs entières :

  • nombre d’enfants ;
  • nombre de livres lus ;
  • nombre de sources d’information utilisées.

5.11.2 Continue

Une mesure peut théoriquement prendre de nombreuses valeurs dans un intervalle :

  • revenu ;
  • durée ;
  • poids physique ;
  • température.

Dans la pratique, une variable continue peut être arrondie ou enregistrée en entiers. Là encore, le stockage ne définit pas seul le concept.

5.12 Les codes spéciaux

Les enquêtes utilisent souvent des codes placés en dehors de la plage des réponses normales.

Dans notre jeu :

  • 97 : souvent « sans objet » pour les questions liées au travail ;
  • 98 : « ne sait pas » ;
  • 99 : « refus » ;
  • 99997, 99998 : codes spéciaux du revenu afin de ne pas entrer en collision avec des revenus plausibles.

5.12.1 Pourquoi distinguer « sans objet » de « refus » ?

Prenons heures_travail :

  • une personne retraitée n’a pas à répondre à la question : absence structurelle / sans objet ;
  • une personne en emploi qui refuse de donner son nombre d’heures présente une non-réponse à une question applicable.

Transformer immédiatement les deux situations en un même NA peut être acceptable pour certains calculs, mais seulement après avoir conservé ou documenté la raison de l’absence.

Le chapitre 7 développera ce point.

5.13 L’univers d’une question

Le dictionnaire indique pour heures_travail et teletravail_jours un univers lié à l’emploi. Cela permet un contrôle logique :

# Pseudo-code conceptuel
si statut_emploi != "en emploi" :
    heures_travail devrait être "sans objet"

Un fichier peut donc être techniquement valide tout en contenant une incohérence de questionnaire. La documentation permet de formuler les règles de validation du chapitre 6.

5.14 Produire un inventaire des variables

Sur un CSV, on peut créer un inventaire minimal :

Afficher le code R
enquete_csv <- readr::read_csv(
  "data/raw/enqueter_brut.csv",
  show_col_types = FALSE
)

inventaire <- tibble::tibble(
  variable = names(enquete_csv),
  classe_r = vapply(enquete_csv, function(x) class(x)[1], character(1)),
  n_distinct = vapply(enquete_csv, dplyr::n_distinct, integer(1)),
  n_manquant = vapply(enquete_csv, function(x) sum(is.na(x)), integer(1))
)

inventaire
# A tibble: 36 × 4
   variable      classe_r n_distinct n_manquant
   <chr>         <chr>         <int>      <int>
 1 id            numeric        3592          0
 2 strate        numeric           6          0
 3 psu           numeric          72          0
 4 poids_base    numeric        2945          0
 5 poids_final   numeric        2960          0
 6 territoire    numeric           5          0
 7 mode_collecte numeric           3          0
 8 sexe          numeric           4          0
 9 age           numeric          68          0
10 diplome       numeric           9          0
# ℹ 26 more rows

Attention : dans le fichier brut, les codes 98 et 99 ne sont pas encore des NA. Le nombre de valeurs manquantes R ne mesure donc pas toute la non-réponse d’enquête.

5.14.1 Joindre l’inventaire au dictionnaire

Afficher le code R
dictionnaire <- readr::read_csv(
  "data/documentation/dictionnaire_variables.csv",
  show_col_types = FALSE
)

inventaire_documente <- inventaire |>
  dplyr::left_join(
    dplyr::select(dictionnaire, variable, libelle, type_conceptuel, codes_speciaux),
    by = "variable"
  )

Cette jointure rapproche ce que R observe de ce que la documentation déclare.

NoteUne bonne pratique très rentable

Pour une enquête inconnue, construire rapidement un tableau « variable / label / classe R / nombre de modalités / codes spéciaux » donne souvent une compréhension plus fiable que de parcourir directement des centaines de colonnes dans un tableur.

5.15 Vérifier la correspondance dictionnaire–fichier

Les variables documentées existent-elles toutes dans le fichier ?

Afficher le code R
setdiff(dictionnaire$variable, names(enquete_csv))
character(0)

Et inversement :

Afficher le code R
setdiff(names(enquete_csv), dictionnaire$variable)
character(0)

Un résultat vide est rassurant. Un écart peut être légitime — variable technique ajoutée, version différente du fichier — mais il doit être expliqué.

5.16 Mini-exercices

5.16.1 Mini-exercice 1 — Nature versus stockage

Pour chaque variable, indiquez un type conceptuel probable :

  • id = 10045 ;
  • poids_final = 1.37 ;
  • sante = 1, 2, 3, 4, 5 ;
  • nb_enfants = 0, 1, 2, 3... ;
  • territoire = 1, 2, 3, 4, 5.

id est un identifiant ; poids_final un poids numérique ; sante une variable ordinale ; nb_enfants un compte quantitatif discret ; territoire une variable nominale malgré son codage numérique.

5.16.2 Mini-exercice 2 — Codes spéciaux

Pourquoi ne faut-il pas calculer directement :

mean(enquete$revenu_mensuel)

si 99997 = ne sait pas et 99998 = refus ?

Ces codes sont de très grands nombres qui ne représentent pas des revenus. Ils gonfleraient artificiellement la moyenne. Il faut d’abord les identifier grâce à la documentation puis les traiter explicitement, en conservant si nécessaire la raison de la non-réponse.

5.17 Exercice de synthèse

5.17.1 Niveau A — Appliquer

À partir de dictionnaire_variables.csv :

  1. listez les variables dont section contient « Opinions » ou « Plan » ;
  2. affichez variable, libelle, type_conceptuel et codes_speciaux ;
  3. comptez le nombre de variables par type_conceptuel.

5.17.2 Niveau B — Choisir

La variable satisfaction_vie est codée de 0 à 10, avec 98 et 99. Discutez trois représentations possibles dans R : numérique, facteur ordonné, facteur nominal. Laquelle conserveriez-vous pour une analyse moyenne ? laquelle pourrait être pertinente pour un tableau descriptif ?

5.17.3 Niveau C — Analyser

Construisez un inventaire automatique du fichier brut avec :

  • nom de variable ;
  • classe R ;
  • nombre de valeurs distinctes ;
  • nombre de NA natifs ;
  • label et type conceptuel issus du dictionnaire.

Identifiez ensuite trois variables pour lesquelles la classe R seule serait insuffisante ou trompeuse pour choisir une méthode statistique.

5.17.4 Correction détaillée

dictionnaire |>
  filter(grepl("Opinions|Plan", section)) |>
  select(variable, libelle, type_conceptuel, codes_speciaux)

dictionnaire |>
  count(type_conceptuel, sort = TRUE)

L’objectif est de manipuler la documentation comme un jeu de données, plutôt que de la traiter comme une annexe rarement consultée.

Pour une moyenne, la représentation numérique 0–10 conserve l’échelle et permet de calculer directement des statistiques après traitement des codes spéciaux. Un facteur ordonné peut être utile si l’on veut insister sur les catégories ordonnées ou ajuster un modèle ordinal. Un facteur nominal perd l’ordre et serait généralement moins pertinent ici. Aucun choix ne doit faire oublier que l’interprétation d’un écart de 1 point sur une échelle de satisfaction mérite elle aussi une réflexion substantive.

5.18 À retenir

  • Les données d’enquête doivent être lues avec leur questionnaire et leur dictionnaire.
  • Nom, label, code et label de valeur sont des objets distincts.
  • Il faut distinguer type conceptuel, type de stockage et classe R.
  • haven_labelled conserve des métadonnées utiles ; il ne doit pas être converti aveuglément (Wickham et al. 2026).
  • {labelled} permet d’inspecter labels et dictionnaires de variables (Larmarange 2026).
  • Les codes spéciaux doivent être identifiés avant les calculs.
  • « Sans objet » n’est pas synonyme de « refus ».
  • L’univers d’une question permet de tester la cohérence entre variables.
  • Une jointure entre inventaire technique et dictionnaire est un excellent point de départ d’audit.

5.19 Pour aller plus loin

La documentation de {haven} détaille la représentation des données étiquetées importées depuis les logiciels statistiques (Wickham et al. 2026). Le package {labelled} fournit des fonctions destinées à la manipulation et à la documentation de ces données (Larmarange 2026).

Nous disposons maintenant de deux sources d’information : le fichier brut et sa documentation. Le chapitre suivant va les confronter pour repérer doublons, valeurs impossibles et incohérences avant de modifier quoi que ce soit.