Aller au contenu

Interopérabilité des standards

À qui s'adresse cette page ?

Cette page est destinée aux équipes qui utilisent à la fois les métadonnées DDI et les structures de données SDMX et souhaitent les relier dans le même graphe. Si vous ne travaillez pas avec SDMX, vous pouvez passer cette page.

SDMX (Statistical Data and Metadata eXchange) est une norme internationale pour partager des statistiques entre organisations comme les banques centrales, les agences gouvernementales et Eurostat. Elle décrit les structures de données — quelles colonnes existent dans un jeu de données, quelles valeurs sont autorisées et comment elles se rapportent les unes aux autres.

DDI décrit les métadonnées d'enquête — quelles questions ont été posées, quelles variables ont été collectées et ce que signifient les réponses. Ces deux standards décrivent les mêmes données sous des angles différents, et un graphe facilite leur liaison.


Pourquoi les graphes pour l'interopérabilité ?

Les approches traditionnelles de la mise en correspondance des standards reposent sur des scripts de transformation, des feuilles de style XSLT ou des schémas relationnels rigides. Ces approches peinent avec :

  • Évolution du schéma : L'ajout de nouvelles correspondances nécessite des modifications de code
  • Relations plusieurs-à-plusieurs : Un seul concept DDI peut correspondre à plusieurs composants SDMX
  • Correspondances contextuelles : Le même élément peut être mis en correspondance différemment selon le contexte
  • Traçabilité : Difficile d'auditer pourquoi une correspondance a été établie

Les bases de données graphe répondent à ces défis grâce à leur schéma flexible et leur modélisation explicite des relations.

Avantages du graphe

Défi Approche relationnelle Approche graphe
Modifications du schéma ALTER TABLE, migrations Ajout dynamique de nouveaux types de nœuds/relations
Plusieurs-à-plusieurs Tables de jonction Relations directes avec propriétés
Contexte JOINs complexes Traversée de chemins spécifiques
Traçabilité Tables d'audit Les propriétés des relations capturent la provenance

Motif d'intégration DDI-SDMX

La tâche principale est de relier les variables DDI aux composants de structure de données SDMX.

Dans SDMX, chaque variable dans un jeu de données joue l'un des deux rôles suivants :

  • Dimension — une colonne qui identifie un point de données (ex. : pays, année, groupe d'âge). Les dimensions indiquent à quoi une valeur fait référence.
  • Mesure — le nombre réel rapporté (ex. : taux de chômage, nombre de personnes).

Une variable DDI correspond au rôle qu'elle joue dans la structure SDMX.

Chaque variable a aussi un domaine de valeurs — l'ensemble des valeurs autorisées (ex. : une liste de codes de pays, ou une plage numérique). Dans SDMX, cela est représenté par une liste de codes (pour les valeurs catégorielles) ou un type de données (pour les nombres/textes).

Correspondance par identifiant

La façon la plus simple de relier DDI et SDMX est la correspondance par identifiant — quand une variable DDI et un composant SDMX partagent le même identifiant, on peut les relier automatiquement. Cela fonctionne pour la plupart des jeux de données structurés où les identifiants ont été attribués de façon cohérente.

DDI Variable ──────────────────────> SDMX Component
     │                                      │
     ├── ID attribute ◄──── matches ────► ID attribute
     ├── User ID      ◄──── matches ────► User ID
     │                                      │
     └── Value Domain ─────────────────> Dimension Codelist
                       ─────────────────> Measure Data Type

Dans Neo4j, ce lien devient une relation explicite :

// Variable as Dimension
(v:Variable)-[:MAPS_TO_DIMENSION]->(d:Dimension)
(v)-[:HAS_VALUE_DOMAIN]->(vd:ValueDomain)-[:ALIGNED_WITH]->(cl:Codelist)

// Variable as Measure
(v:Variable)-[:MAPS_TO_MEASURE]->(m:Measure)
(v)-[:HAS_VALUE_DOMAIN]->(vd:ValueDomain)-[:ALIGNED_WITH]->(dt:DataType)

Schéma du graphe pour l'intégration

// DDI nodes (from ddigraph)
(:Variable {id, name, label, user_id})
(:ValueDomain {id, type})
(:CodeList {id, name})
(:Category {id, label, code_value})

// SDMX nodes
(:DataStructureDefinition {id, agency, version})
(:Dimension {id, position, concept_identity})
(:Measure {id, concept_identity})
(:Codelist {id, agency, version})  // SDMX codelist
(:Code {id, value, name})

// Integration relationships
(:Variable)-[:MAPS_TO_DIMENSION {match_type, confidence}]->(:Dimension)
(:Variable)-[:MAPS_TO_MEASURE {match_type, confidence}]->(:Measure)
(:CodeList)-[:ALIGNED_WITH {mapping_date, method}]->(:Codelist)
(:Category)-[:CORRESPONDS_TO]->(:Code)

Création des correspondances

Exécutez ces requêtes Cypher pour créer les liens. La première requête correspond par user_id (la correspondance la plus fiable) ; la seconde utilise le champ id brut comme solution de repli :

// Match DDI variables to SDMX dimensions by user_id
MATCH (v:Variable)
WHERE v.user_id IS NOT NULL
MATCH (d:Dimension)
WHERE d.id = v.user_id OR d.concept_identity = v.user_id
MERGE (v)-[m:MAPS_TO_DIMENSION]->(d)
SET m.match_type = 'user_id',
    m.matched_on = datetime(),
    m.confidence = 1.0
RETURN v.name, d.id, m.match_type
// Match by ID attribute
MATCH (v:Variable)
MATCH (d:Dimension)
WHERE d.id = v.id
MERGE (v)-[m:MAPS_TO_DIMENSION]->(d)
SET m.match_type = 'id',
    m.matched_on = datetime(),
    m.confidence = 0.9
RETURN v.name, d.id, m.match_type

Alignement des domaines de valeurs

Une fois les variables mises en correspondance avec les dimensions, leurs domaines de valeurs doivent être alignés avec les listes de codes SDMX :

// Find DDI CodeLists that should align with SDMX Codelists
MATCH (v:Variable)-[:MAPS_TO_DIMENSION]->(d:Dimension)
MATCH (v)-[:HAS_VALUE_DOMAIN]->(:ValueDomain)-[:USES_CODELIST]->(ddi_cl:CodeList)
MATCH (d)-[:HAS_LOCAL_REPRESENTATION]->(sdmx_cl:Codelist)
MERGE (ddi_cl)-[a:ALIGNED_WITH]->(sdmx_cl)
SET a.alignment_date = datetime()
RETURN ddi_cl.name, sdmx_cl.id
// Map individual categories to codes
MATCH (ddi_cl:CodeList)-[:ALIGNED_WITH]->(sdmx_cl:Codelist)
MATCH (ddi_cl)-[:HAS_CATEGORY]->(cat:Category)
MATCH (sdmx_cl)-[:HAS_CODE]->(code:Code)
WHERE cat.code_value = code.value
MERGE (cat)-[:CORRESPONDS_TO]->(code)
RETURN cat.label, code.name

Interrogation des données intégrées

Trouver toutes les variables mises en correspondance

MATCH (v:Variable)-[m:MAPS_TO_DIMENSION|MAPS_TO_MEASURE]->(component)
RETURN v.name AS variable,
       type(m) AS mapping_type,
       labels(component)[0] AS component_type,
       component.id AS component_id,
       m.confidence AS confidence
ORDER BY m.confidence DESC

Tracer la lignée complète

// From DDI question to SDMX dimension
MATCH path = (q:QuestionItem)<-[:ASKS_QUESTION]-(:QuestionConstruct)
             <-[:HAS_CONSTRUCT*]-(seq:Sequence),
      (v:Variable)-[:MAPS_TO_DIMENSION]->(d:Dimension)
WHERE v.question_id = q.fragment_id
RETURN q.name AS question,
       v.name AS variable,
       d.id AS sdmx_dimension,
       length(path) AS depth

Trouver les variables non mises en correspondance

MATCH (v:Variable)
WHERE NOT (v)-[:MAPS_TO_DIMENSION|MAPS_TO_MEASURE]->()
RETURN v.id, v.name, v.user_id
ORDER BY v.name

Rapport d'alignement des listes de codes

MATCH (ddi_cl:CodeList)-[:ALIGNED_WITH]->(sdmx_cl:Codelist)
OPTIONAL MATCH (ddi_cl)-[:HAS_CATEGORY]->(cat:Category)
OPTIONAL MATCH (cat)-[:CORRESPONDS_TO]->(code:Code)
WITH ddi_cl, sdmx_cl,
     count(DISTINCT cat) AS ddi_categories,
     count(DISTINCT code) AS mapped_codes
RETURN ddi_cl.name AS ddi_codelist,
       sdmx_cl.id AS sdmx_codelist,
       ddi_categories,
       mapped_codes,
       round(100.0 * mapped_codes / ddi_categories) AS pct_mapped

Avantages de l'approche graphe

1. Cardinalité flexible des correspondances

Une seule variable DDI peut correspondre à plusieurs composants SDMX (ou inversement) sans modification du schéma :

// Variable maps to both dimension and attribute
(v:Variable)-[:MAPS_TO_DIMENSION]->(d:Dimension)
(v:Variable)-[:MAPS_TO_ATTRIBUTE]->(a:Attribute)

2. Métadonnées de correspondance riches

Les relations portent des propriétés qui documentent la correspondance :

[:MAPS_TO_DIMENSION {
  match_type: 'user_id',      // How the match was made
  confidence: 0.95,           // Confidence score
  matched_on: datetime(),     // When
  matched_by: 'auto',         // Who/what
  notes: 'Verified by SME'    // Documentation
}]

3. Enrichissement incrémental

Ajoutez de nouveaux types de correspondance sans modifier les données existantes :

// Later: add semantic similarity mappings
MATCH (v:Variable), (d:Dimension)
WHERE gds.similarity.cosine(v.embedding, d.embedding) > 0.8
MERGE (v)-[m:MAPS_TO_DIMENSION]->(d)
SET m.match_type = 'semantic',
    m.confidence = gds.similarity.cosine(v.embedding, d.embedding)

4. Navigation bidirectionnelle

Interrogez depuis la perspective de chaque standard :

// DDI-first: What SDMX components does this variable map to?
MATCH (v:Variable {name: 'AGE'})-[:MAPS_TO_DIMENSION|MAPS_TO_MEASURE]->(c)
RETURN c

// SDMX-first: What DDI variables feed this dimension?
MATCH (d:Dimension {id: 'AGE'})<-[:MAPS_TO_DIMENSION]-(v:Variable)
RETURN v

5. Analyse d'impact

Comprendre les effets en aval des modifications :

// If we change this CodeList, what SDMX structures are affected?
MATCH (cl:CodeList {id: 'CL_SEX'})-[:ALIGNED_WITH]->(sdmx_cl:Codelist)
      <-[:HAS_LOCAL_REPRESENTATION]-(d:Dimension)
      <-[:HAS_DIMENSION]-(dsd:DataStructureDefinition)
RETURN dsd.id AS affected_structure, d.id AS via_dimension

Implémentation avec ddigraph

Étape 1 : Charger les données DDI

ddigraph load survey.xml --format lifecycle

Étape 2 : Charger la structure SDMX

Créer les nœuds SDMX (exemple en Cypher) :

// Load DSD
CREATE (dsd:DataStructureDefinition {
  id: 'DSD_LFS',
  agency: 'EUROSTAT',
  version: '1.0'
})

// Load Dimensions
CREATE (d:Dimension {id: 'FREQ', position: 1, concept_identity: 'FREQ'})
CREATE (d:Dimension {id: 'GEO', position: 2, concept_identity: 'GEO'})
// ... etc

Étape 3 : Exécuter les requêtes de correspondance

Lancez les requêtes de poignée de main pour créer les relations d'intégration.

Étape 4 : Valider et rapporter

// Summary statistics
MATCH (v:Variable)
OPTIONAL MATCH (v)-[m:MAPS_TO_DIMENSION]->(d)
OPTIONAL MATCH (v)-[m2:MAPS_TO_MEASURE]->(measure)
RETURN count(v) AS total_variables,
       count(d) AS mapped_to_dimension,
       count(measure) AS mapped_to_measure,
       count(v) - count(d) - count(measure) AS unmapped

Conclusion

Les bases de données graphe transforment l'interopérabilité des standards, d'un processus fragile et lourd en code, en un modèle de données flexible et interrogeable. La représentation explicite des correspondances sous forme de relations permet :

  • Une logique d'intégration auto-documentée
  • Une extension facile vers de nouveaux types de correspondance
  • Des requêtes puissantes de lignée et d'impact
  • Un raffinement incrémental des correspondances au fil du temps

Pour l'intégration DDI-SDMX en particulier, le modèle en graphe représente naturellement la "poignée de main" entre les identifiants de variables et les identifiants de composants, tout en préservant le contexte complet nécessaire pour comprendre et maintenir les correspondances.