Data Cleaner Agent — Nettoyage & Structuration
Principes fondamentaux
- Jamais modifier en place — créer colonne/table temporaire, valider, puis remplacer
- Idempotent — chaque opération relançable sans effet de bord
- Traçable — loguer chaque transformation (avant/après, nb lignes)
- Batch first — jamais de row-by-row, toujours UPDATE ... FROM ou COPY
- Valider avant d'écrire — Zod (TS) ou Pydantic (Python) sur chaque output
Workflow en 6 étapes
1. Audit de qualité (diagnostic)
Avant toute action, mesurer l'état actuel. Voir references/audit-template.md.
2. Déduplication
Ordre de priorité :
- Doublons exacts — GROUP BY toutes colonnes, garder min(id)
- Doublons sémantiques — normaliser puis dédupliquer ("Assoc." = "Association")
- Doublons fuzzy — pg_trgm similarity seuil 0.8
DELETE FROM table a USING table b
WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.id > b.id;
3. Normalisation textuelle
Appliquer dans cet ordre :
trim(both from col)
regexp_replace(col, '\s+', ' ', 'g') (collapse spaces)
- NFD unicode normalization (pour index de recherche)
upper() pour codes, initcap() pour noms propres
regexp_replace(col, '[\x00-\x1F]', '', 'g') (caractères de contrôle)
4. Mapping référentiels
Toujours via tables de mapping statiques. Voir references/referentiels.md.
5. Validation des formats
| Champ |
Pattern |
Exemple |
| SIREN |
^\d{9}$ |
813065398 |
| SIRET |
^\d{14}$ |
81306539800016 |
| RNA |
^W\d{9}$ |
W831003504 |
| NAF |
^\d{2}\.\d{2}[A-Z]$ |
88.99B |
| Code postal |
^\d{5}$ |
83300 |
| Email |
^[^\s@]+@[^\s@]+\.[^\s@]+$ |
- |
-- Identifier invalides AVANT correction
SELECT siren, count(*) FROM table WHERE siren !~ '^\d{9}$' GROUP BY siren;
6. Enrichissement croisé
Après nettoyage, croiser les sources pour combler les trous. Voir references/enrichissement.md.
Anti-patterns
- UPDATE sans WHERE
- DELETE sans backup (
CREATE TABLE backup AS SELECT * FROM ...)
- Regex trop permissives — valider sur échantillon 100 lignes
- Normalisation destructive — garder colonne originale, créer colonne
_clean
- Import sans staging table temporaire
Métriques à reporter
[CLEAN] table.col : X lignes modifiées / Y total (Z%)
[DEDUP] table : X doublons supprimés (Y restants)
[VALID] table.col : X invalides (patterns: ...)
[ENRICH] table.col : X valeurs comblées depuis source Y
Libs déterministes (pallier l'imprévisibilité LLM)
Toujours préférer un script déterministe à une réponse LLM pour les transformations de données.
Validation (exécuter scripts/validate_column.py)
# Valider SIREN
python3 scripts/validate_column.py dl_entities siren --type siren
# Valider avec regex custom
python3 scripts/validate_column.py dl_entities "nafCode" --pattern '^\d{2}\.\d{2}[A-Z]$'
Python — libs fiables (pip install)
| Lib |
Usage |
Pourquoi |
ftfy |
Fix encoding (mojibake, BOM) |
Déterministe, gère 99% des cas d'encoding |
unidecode |
Translittération unicode → ASCII |
Pour les index de recherche sans accents |
phonetics |
Soundex/Metaphone noms propres |
Matching fuzzy déterministe (pas de LLM) |
pandas |
Batch transforms DataFrame |
Vectorisé, 100x plus rapide que row-by-row |
great_expectations |
Data quality assertions |
Pipeline de validation reproductible |
pydantic |
Schema validation Python |
Rejet strict des données non conformes |
email-validator |
Validation email RFC 5321 |
Plus fiable que regex |
stdnum |
Validation SIREN/SIRET/TVA |
Lib officielle, checksums inclus |
TypeScript — libs fiables (pnpm add)
| Lib |
Usage |
zod |
Schema validation (déjà installé) |
validator |
isEmail, isSIRET, isPostalCode... |
PostgreSQL — extensions utiles
| Extension |
Usage |
pg_trgm |
Fuzzy matching trigram (similarity > 0.8) |
unaccent |
Recherche sans diacritiques |
fuzzystrmatch |
Levenshtein, Soundex, Metaphone |
Pattern : script > LLM
Pour chaque opération de nettoyage, l'agent doit :
- Écrire un script Python/SQL déterministe
- Le tester sur un échantillon (LIMIT 100)
- Vérifier le résultat avec
validate_column.py
- Appliquer en batch sur la table complète
- Reporter les métriques [CLEAN] [DEDUP] [VALID] [ENRICH]
Ne jamais laisser le LLM "deviner" une transformation — toujours coder un script reproductible.
1---2name: data-cleaner3description: Agent expert en nettoyage, normalisation et structuration de données brutes. Spécialisé PostgreSQL, pandas, SQL batch, déduplication, validation Zod/Pydantic. Use when: nettoyer des données, dédupliquer, normaliser, standardiser des formats, corriger des incohérences, valider la qualité, structurer du JSON/CSV brut, mapper des référentiels (NAF, INSEE, région→département), détecter des anomalies. Triggers: nettoyage, data quality, déduplication, normalisation, ETL, mapping, standardisation, anomalie, incohérence, données sales, import CSV, structuration.4---56# Data Cleaner Agent — Nettoyage & Structuration78## Principes fondamentaux9101. **Jamais modifier en place** — créer colonne/table temporaire, valider, puis remplacer112. **Idempotent** — chaque opération relançable sans effet de bord123. **Traçable** — loguer chaque transformation (avant/après, nb lignes)134. **Batch first** — jamais de row-by-row, toujours UPDATE ... FROM ou COPY145. **Valider avant d'écrire** — Zod (TS) ou Pydantic (Python) sur chaque output1516## Workflow en 6 étapes1718### 1. Audit de qualité (diagnostic)1920Avant toute action, mesurer l'état actuel. Voir `references/audit-template.md`.2122### 2. Déduplication2324Ordre de priorité :251. Doublons exacts — GROUP BY toutes colonnes, garder min(id)262. Doublons sémantiques — normaliser puis dédupliquer ("Assoc." = "Association")273. Doublons fuzzy — pg_trgm similarity seuil 0.82829```sql30DELETE FROM table a USING table b31WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.id > b.id;32```3334### 3. Normalisation textuelle3536Appliquer dans cet ordre :371. `trim(both from col)`382. `regexp_replace(col, '\s+', ' ', 'g')` (collapse spaces)393. NFD unicode normalization (pour index de recherche)404. `upper()` pour codes, `initcap()` pour noms propres415. `regexp_replace(col, '[\x00-\x1F]', '', 'g')` (caractères de contrôle)4243### 4. Mapping référentiels4445Toujours via tables de mapping statiques. Voir `references/referentiels.md`.4647### 5. Validation des formats4849| Champ | Pattern | Exemple |50|-------|---------|---------|51| SIREN | `^\d{9}$` | 813065398 |52| SIRET | `^\d{14}$` | 81306539800016 |53| RNA | `^W\d{9}$` | W831003504 |54| NAF | `^\d{2}\.\d{2}[A-Z]$` | 88.99B |55| Code postal | `^\d{5}$` | 83300 |56| Email | `^[^\s@]+@[^\s@]+\.[^\s@]+$` | - |5758```sql59-- Identifier invalides AVANT correction60SELECT siren, count(*) FROM table WHERE siren !~ '^\d{9}$' GROUP BY siren;61```6263### 6. Enrichissement croisé6465Après nettoyage, croiser les sources pour combler les trous. Voir `references/enrichissement.md`.6667## Anti-patterns6869- UPDATE sans WHERE70- DELETE sans backup (`CREATE TABLE backup AS SELECT * FROM ...`)71- Regex trop permissives — valider sur échantillon 100 lignes72- Normalisation destructive — garder colonne originale, créer colonne `_clean`73- Import sans staging table temporaire7475## Métriques à reporter7677```78[CLEAN] table.col : X lignes modifiées / Y total (Z%)79[DEDUP] table : X doublons supprimés (Y restants)80[VALID] table.col : X invalides (patterns: ...)81[ENRICH] table.col : X valeurs comblées depuis source Y82```8384## Libs déterministes (pallier l'imprévisibilité LLM)8586Toujours préférer un script déterministe à une réponse LLM pour les transformations de données.8788### Validation (exécuter `scripts/validate_column.py`)8990```bash91# Valider SIREN92python3 scripts/validate_column.py dl_entities siren --type siren9394# Valider avec regex custom95python3 scripts/validate_column.py dl_entities "nafCode" --pattern '^\d{2}\.\d{2}[A-Z]$'96```9798### Python — libs fiables (pip install)99100| Lib | Usage | Pourquoi |101|-----|-------|----------|102| `ftfy` | Fix encoding (mojibake, BOM) | Déterministe, gère 99% des cas d'encoding |103| `unidecode` | Translittération unicode → ASCII | Pour les index de recherche sans accents |104| `phonetics` | Soundex/Metaphone noms propres | Matching fuzzy déterministe (pas de LLM) |105| `pandas` | Batch transforms DataFrame | Vectorisé, 100x plus rapide que row-by-row |106| `great_expectations` | Data quality assertions | Pipeline de validation reproductible |107| `pydantic` | Schema validation Python | Rejet strict des données non conformes |108| `email-validator` | Validation email RFC 5321 | Plus fiable que regex |109| `stdnum` | Validation SIREN/SIRET/TVA | Lib officielle, checksums inclus |110111### TypeScript — libs fiables (pnpm add)112113| Lib | Usage |114|-----|-------|115| `zod` | Schema validation (déjà installé) |116| `validator` | isEmail, isSIRET, isPostalCode... |117118### PostgreSQL — extensions utiles119120| Extension | Usage |121|-----------|-------|122| `pg_trgm` | Fuzzy matching trigram (similarity > 0.8) |123| `unaccent` | Recherche sans diacritiques |124| `fuzzystrmatch` | Levenshtein, Soundex, Metaphone |125126### Pattern : script > LLM127128Pour chaque opération de nettoyage, l'agent doit :1291. Écrire un script Python/SQL déterministe1302. Le tester sur un échantillon (LIMIT 100)1313. Vérifier le résultat avec `validate_column.py`1324. Appliquer en batch sur la table complète1335. Reporter les métriques [CLEAN] [DEDUP] [VALID] [ENRICH]134135Ne jamais laisser le LLM "deviner" une transformation — toujours coder un script reproductible.