LLM · Qualité des données · Pandas · 2026-06-12 · Intermédiaire

Nettoyer un CSV avec l’aide d’un LLM

Détecter les anomalies textuelles d’un petit CSV, demander des propositions au modèle et appliquer uniquement des corrections vérifiables.

Une gomme et des tableaux avant et après correction représentent le nettoyage contrôlé d’un CSV.
Illustration de couverture du tutoriel.
Note moyenne— / 5

Objectif à réaliser

Produire un CSV nettoyé et un journal qui sépare les corrections automatiques des lignes nécessitant une validation humaine.

Schéma d’un nettoyage CSV où le profilage et une table de référence valident les propositions du modèle.
Profilage, propositions du modèle, validation et journal des corrections.
Durée60 minutes
Prérequis
  • Python 3.11 ou plus récent
  • Bases de pandas et du contrôle qualité
  • Un endpoint LLM compatible, ou le mode --mock fourni
Mots-clés
LLMpandasqualité des donnéesCSV
Environnement vérifiéPython 3.11 et pandas 2mock · Linux, macOS, Windows WSL

Figures du tutoriel

Flux détaillé reliant CSV bruité, proposition du LLM, référentiel d’arbitrage et fichiers de sortie.
Les valeurs ambiguës restent visibles dans la trace au lieu d’être corrigées silencieusement.
← Retour aux tutoriels

Objectifs et livrables

Un export CSV peut contenir « Casa », « Casablanca », des espaces superflus et plusieurs écritures d’une même catégorie. Nous allons utiliser un LLM pour proposer des rapprochements, puis nous appuyer sur un référentiel et des règles Python pour décider des corrections à appliquer.

Vous commencerez par préparer le fichier bruité et les valeurs de référence. Nous demanderons ensuite des propositions structurées au modèle, vérifierons leur conformité et appliquerons les changements acceptés. Les valeurs ambiguës permettront de voir comment le programme signale une ligne à revoir.

Ce parcours rend chaque décision explicable : quelle valeur a été reçue, quelle correction a été proposée et pourquoi a-t-elle été retenue ou refusée ? Nous examinerons la trace des changements en parallèle du fichier nettoyé, afin de pouvoir comparer le résultat aux données de départ.

À la fin, vous aurez outputs/clean.csv, outputs/changes.jsonl et un compteur de lignes à examiner. Ces fichiers vous donneront une base pour vérifier la qualité du nettoyage et faire évoluer les règles avec votre propre référentiel.

Lire le flux avant de coder

Le schéma positionne le LLM comme un proposeur de correspondances. Le référentiel contient les valeurs autorisées et le code Python décide si une proposition est suffisamment sûre pour être appliquée. Les valeurs ambiguës sont conservées dans le journal plutôt que forcées vers une catégorie plausible.

Pour chaque correction, comparez la valeur d’origine, la proposition, la règle utilisée et le résultat écrit dans clean.csv. Cette lecture rend le nettoyage réversible et permet de corriger le référentiel sans perdre les décisions déjà prises.

1. Préparer l’environnement

Séparez dès le départ les fichiers d’entrée, les propositions du modèle et les données exportées. Le CSV original doit rester le point de comparaison : une nouvelle exécution pourra ainsi être relue sans perdre les valeurs qui ont motivé les corrections. Installez les dépendances dans l’environnement virtuel, puis exécutez les commandes depuis la racine du projet.

Le chargement avec dtype=str conserve les cellules sous forme de chaînes, ce qui évite une conversion implicite des libellés ou d’éventuels identifiants numériques. fillna("") remplace les valeurs manquantes par une chaîne vide ; cela facilite les comparaisons, mais ne constitue pas une correction métier. Une cellule vide restera à examiner si aucune règle ne permet de la compléter.

Code de l’étape

mkdir -p llm-nettoyage-csv/{data,src,outputs}
cd llm-nettoyage-csv
python3 -m venv .venv && source .venv/bin/activate
python -m pip install pandas

Sortie obtenue

Successfully installed pandas

Commande de vérification

python -c "import pandas as pd; print(pd.__version__)"

2. Créer le CSV bruité et les règles

Le référentiel définit les libellés vers lesquels une correction peut converger. Les variantes orthographiques servent à tester les rapprochements simples ; les cas ambigus et la ville absente du référentiel permettent de vérifier que le programme n’impose pas une réponse arbitraire. Parcourez ces lignes avec les listes de villes et de catégories avant d’interroger le modèle.

Conservez une distinction entre une valeur incorrecte et une valeur inconnue. Une nouvelle ville peut être légitime même si elle ne figure pas encore dans la liste autorisée. Le tutoriel l’oriente vers la revue plutôt que d’enrichir automatiquement le référentiel. Cette séparation rend le résultat plus utile : on peut améliorer les données sans transformer chaque suggestion du modèle en règle.

Créez data/contacts.csv avec seize lignes et les colonnes name,city,category. Ajoutez data/reference.json avec trois villes et trois catégories autorisées. Le jeu contient des variations de casse, des espaces parasites, une nouvelle ville valide et deux valeurs réellement ambiguës.

Extrait de data/contacts.csv

Le tableau ci-dessous reprend quelques lignes du fichier source. Le symbole ␠ représente un espace final volontairement conservé pour rendre l’anomalie visible dans l’aperçu.

Nom Ville Catégorie
Amina Rabat student
Youssef Casablanca review
Sara rabat student
Omar Casablanca␠ review
Nadia Rabat student
Mehdi Casablanca review

Cet extrait permet de repérer immédiatement les écarts de casse et les espaces parasites avant l’étape de normalisation.

Sortie obtenue

Le jeu contient six variations volontaires, une nouvelle ville et deux lignes ambiguës.

rows=16 columns=3 variations=6 valid_new_values=2 ambiguous_rows=2

Commande de vérification

python -c "import pandas as pd; print(pd.read_csv('data/contacts.csv').shape)"

Code de l’étape

import json
import pandas as pd

rows = pd.read_csv("data/contacts.csv", dtype=str).fillna("")
reference = json.loads(open("data/reference.json", encoding="utf-8").read())
print(rows.shape, reference.keys())

3. Demander une proposition structurée

Le modèle propose des opérations ; il ne reçoit pas l’autorisation de modifier directement le tableau. Chaque proposition associe un numéro de ligne, un champ, une ancienne valeur et une nouvelle valeur. Cette forme permet au programme de contrôler précisément la modification, au lieu de remplacer le CSV par une version entièrement réécrite dont les différences seraient difficiles à expliquer.

Le champ confidence est une estimation fournie dans la proposition, pas une probabilité calibrée de correction. Il sert ici à appliquer un seuil de tri, en complément des règles locales. Exécutez d’abord le fichier de propositions mock pour comprendre les refus, puis comparez les propositions réelles aux mêmes lignes sans modifier simultanément le seuil ou le référentiel.

Le prompt doit demander une liste JSON de corrections avec row_id, field, old, new, confidence. En mode mock, utilisez les corrections de examples/mock-corrections.json.

Sortie obtenue

Chaque proposition indique la ligne, l’ancienne valeur et la nouvelle valeur ; aucune modification n’est encore appliquée.

proposals=4 applied=0 review=4 output=outputs/proposals.json

Le mode réel utilise src/llm_client.py et écrit la proposition brute dans outputs/proposals.json. Les règles locales restent obligatoires avant toute application.

Code de l’étape

import json
from llm_client import chat

prompt = (
    "Retourne uniquement une liste JSON de corrections avec "
    "row_id, field, old, new et confidence.\n"
    + rows.to_json(orient="records", force_ascii=False)
)
raw = chat([{"role": "user", "content": prompt}])
proposals = json.loads(raw)
open("outputs/proposals.json", "w", encoding="utf-8").write(raw)

Commande de vérification

python src/clean.py --mock --input data/contacts.csv --proposals examples/mock-corrections.json

4. Valider, appliquer et auditer

L’application commence par vérifier que la proposition vise toujours la valeur observée. row_id est numéroté à partir de 1, alors que iloc commence à 0 : la soustraction de 1 relie ces deux conventions. La comparaison avec old évite d’appliquer une correction périmée si le fichier a changé entre la proposition et son traitement.

Lisez les exports ensemble : le CSV contient les valeurs retenues, changes.jsonl décrit les opérations appliquées et review.jsonl conserve les situations non résolues automatiquement. Le nombre de corrections n’est pas nécessairement le nombre de lignes modifiées, car une ligne peut recevoir plusieurs opérations. Comparez enfin le CSV exporté au fichier source, notamment les lignes qui ne devaient pas changer.

Appliquez une correction seulement si new appartient à la référence et si confidence >= 0.9. Écrivez les propositions refusées dans outputs/review.jsonl.

Sortie obtenue

Le CSV nettoyé respecte les listes de référence et chaque changement est traçable.

rows=16 clean=14 accepted=5 review=2 invalid_values=0 changes_log=outputs/changes.jsonl

Commande de vérification

python src/clean.py --mock --check --input data/contacts.csv --proposals examples/mock-corrections.json
python src/quality.py outputs/clean.csv data/reference.json

Code de l’étape

changes, review = [], []
for proposal in proposals:
    row = rows.iloc[proposal["row_id"] - 1]
    accepted = (
        proposal["field"] in reference and
        row[proposal["field"]] == proposal["old"] and
        proposal["new"] in reference[proposal["field"]] and
        float(proposal["confidence"]) >= 0.9
    )
    (changes if accepted else review).append(proposal)
    if accepted:
        rows.loc[proposal["row_id"] - 1, proposal["field"]] = proposal["new"]
rows.to_csv("outputs/clean.csv", index=False)

Exemples de sorties

Le mode mock produit un CSV valide, un journal des changements et au moins une ligne en revue humaine. Une correction silencieuse est considérée comme un échec.

Dépannage et diagnostics

Si le modèle renvoie du Markdown autour du JSON, refusez la réponse ou utilisez une sortie structurée. Conservez le prompt, le modèle et le hash du fichier source.

Vérification finale

  • seize lignes traitées ;
  • valeurs finales dans les référentiels ;
  • modifications et refus journalisés ;
  • ligne ambiguë envoyée en revue.

Limites et prolongements

Le LLM ne remplace pas les règles métier. Pour un volume important, échantillonnez les corrections et mesurez le taux d’acceptation par colonne.

Références

Livrables du tutoriel

Téléchargements

Retrouvez les codes sources et les fichiers nécessaires pour reproduire le résultat présenté.