Introduction
Dans les traitements de données, il est fréquent que les informations utiles soient réparties sur plusieurs tables. Pour exploiter ces données, on doit les fusionner, c’est-à-dire croiser les lignes de deux tables en fonction d’un champ commun. Cette opération est fondamentale dans de nombreux contextes, comme relier une liste d’élèves à leurs résultats ou une base d’articles à leurs fournisseurs. En Python, on manipule pour cela des listes de dictionnaires. Pour que la fusion soit fiable, il est essentiel de vérifier la cohérence des clés, le respect du domaine de valeurs, et l’absence de doublons dans les champs utilisés pour la correspondance.
Fusion simple à partir d’une clé commune
Fusionner deux tables consiste à relier leurs lignes sur la base d’une clé commune, c’est-à-dire un champ dont les valeurs servent de point de jonction. Chaque ligne de la première table est associée à une ligne de la seconde dès lors que leurs valeurs sur ce champ sont identiques.
Exemple :
utilisateurs = [
{'id': 1, 'nom': 'Alice'},
{'id': 2, 'nom': 'Bob'}
]
abonnements = [
{'utilisateur_id': 1, 'forfait': 'Premium'},
{'utilisateur_id': 2, 'forfait': 'Standard'}
]
Même si les noms des champs sont différents (« id » et « utilisateur_id »), ils se réfèrent au même domaine de valeurs : les identifiants uniques des utilisateurs. Ce domaine correspond à l’ensemble des valeurs admissibles pour ce champ, ici les entiers 1 et 2.
Une première méthode consiste à utiliser deux boucles imbriquées :
fusion = []
for utilisateur in utilisateurs:
for abo in abonnements:
if utilisateur['id'] == abo['utilisateur_id']:
fusion.append({
'nom': utilisateur['nom'],
'forfait': abo['forfait']
})
Cette méthode fonctionne, mais n’est pas efficace si les tables sont volumineuses, car chaque ligne de la première table compare toutes les lignes de la seconde.
Accélérer la fusion avec un dictionnaire indexé
Pour améliorer les performances, on peut transformer l’une des tables en dictionnaire indexé, où la clé est la valeur commune et la valeur associée est la ligne correspondante. Cela permet un accès direct sans parcourir toute la table.
Exemple :
index_abonnements = {}
for abo in abonnements:
index_abonnements[abo['utilisateur_id']] = abo['forfait']
Remarque : cette méthode suppose que les valeurs du champ « utilisateur_id » sont uniques dans la table des abonnements. Si ce n’est pas le cas, une correspondance multiple risquerait d’écraser des données. Il est donc indispensable de vérifier l’absence de doublons avant de créer l’index :
cles = [abo['utilisateur_id'] for abo in abonnements]
assert len(set(cles)) == len(cles), "Doublons détectés dans la clé"
Une fois l’index construit, la fusion devient plus rapide :
fusion = []
for utilisateur in utilisateurs:
uid = utilisateur['id']
if uid in index_abonnements:
fusion.append({
'nom': utilisateur['nom'],
'forfait': index_abonnements[uid]
})
Cette version accède directement à la ligne correspondante sans boucle interne, ce qui améliore la lisibilité et l’efficacité.
Prendre en compte les cas particuliers
Les données réelles sont souvent incomplètes ou désynchronisées. Il est donc important d’anticiper les cas où une ligne d’une table n’a aucune correspondance dans l’autre.
Exemple : si un utilisateur n’a pas d’abonnement, il peut être utile d’afficher une valeur par défaut :
fusion = []
for utilisateur in utilisateurs:
uid = utilisateur['id']
forfait = index_abonnements.get(uid, 'Aucun')
fusion.append({
'nom': utilisateur['nom'],
'forfait': forfait
})
Ce traitement évite les erreurs d’accès et rend visible le manque d’information. De tels cas peuvent révéler des anomalies dans les données sources, comme des identifiants manquants ou des suppressions non synchronisées.
Inversement, il peut aussi exister dans la table secondaire des lignes sans correspondance dans la première. On peut les détecter ainsi :
ids_utilisateurs = {u['id'] for u in utilisateurs}
orphelins = [abo for abo in abonnements if abo['utilisateur_id'] not in ids_utilisateurs]
Repérer ces cas permet de contrôler l’intégrité référentielle : toute valeur étrangère (comme un identifiant d’utilisateur dans un abonnement) devrait correspondre à une valeur valide dans la table principale.
Mieux comprendre le domaine de valeurs
Le domaine de valeurs désigne l’ensemble des valeurs possibles pour un champ donné. Lors d’une fusion, il est crucial que les deux champs comparés appartiennent au même domaine : même type, même format, mêmes conventions.
Exemple :
{'utilisateur_id': '2'} # chaîne de caractères
{'id': 2} # entier
Ces deux valeurs semblent identiques mais ne le sont pas dans Python. Un oubli de conversion peut empêcher la fusion, d’où la nécessité de s’assurer de la cohérence des formats.
Vérifier le domaine de valeurs, c’est aussi contrôler que les données ne comportent pas d’incohérences (doublons, valeurs inattendues, types mixtes), ce qui peut compromettre la qualité de la fusion.
🔎 (Facultatif) Fusion sur plusieurs champs
Hors programme officiel de Première NSI
Dans certains cas, il faut fusionner deux tables sur plus d’un champ. On parle alors de condition composée (ou conjonction de tests). Cela se produit lorsqu’une seule colonne ne suffit pas à garantir une correspondance fiable.
Exemple :
personnes = [
{'nom': 'Alice', 'prenom': 'Marie'},
{'nom': 'Dupont', 'prenom': 'Jean'}
]
notes = [
{'nom': 'Alice', 'prenom': 'Marie', 'note': 15},
{'nom': 'Dupont', 'prenom': 'Jean', 'note': 12}
]
fusion = []
for p in personnes:
for n in notes:
if p['nom'] == n['nom'] and p['prenom'] == n['prenom']:
fusion.append({
'nom': p['nom'],
'prenom': p['prenom'],
'note': n['note']
})
⚠️ Cette méthode, bien qu’utile pour comprendre le principe, peut être risquée dans la réalité. Les noms et prénoms ne garantissent pas toujours une identification unique (cas d’homonymie). Il est donc préférable de s’appuyer sur des identifiants stables et uniques.
Conclusion
Fusionner deux tables permet d’enrichir les données en croisant des informations complémentaires. Pour que cette opération soit fiable, il faut s’assurer que les clés de correspondance sont uniques, que leur domaine de valeurs est cohérent, et que les cas particuliers sont anticipés. La création d’un dictionnaire indexé permet d’optimiser la fusion, tout en gardant une structure claire et efficace. Ces compétences sont fondamentales pour manipuler des données en Python et préparent à des notions plus avancées comme les bases de données relationnelles.
À retenir
Fusionner deux tables revient à relier leurs lignes à partir d’un champ commun. Cela nécessite de vérifier l’unicité des clés, la cohérence du domaine de valeurs et la gestion des cas sans correspondance. Utiliser un dictionnaire indexé permet d’accélérer cette opération.
