datacraftIACopilotqualitéproductiondata analyst

Code data généré par l'IA : les 7 vérifications à faire avant de le laisser produire un chiffre

GP
Gaël Penessot

Le code généré par une IA passe rarement à côté de la syntaxe. Il passe à côté du métier : une jointure qui duplique, un groupby à la mauvaise granularité, une moyenne calculée sur des NaN silencieusement ignorés. Le script tourne, ne lève aucune erreur, et sort un chiffre faux.

C'est un déplacement du travail, pas une disparition : votre valeur passe de l'écriture du code à sa validation.

Ce que l'IA rate systématiquement

Trois catégories, dans l'ordre de gravité observée :

Catégorie Ce que l'IA produit Ce qui est faux
Granularité df.groupby("client").sum() Somme aussi les identifiants et les prix unitaires
Valeurs manquantes df["marge"].mean() Ignore les NaN sans le dire, moyenne sur un sous-ensemble
Sémantique métier df["ca"].sum() Utilise la colonne ca de la source au lieu de recalculer

Aucun de ces trois cas ne lève d'exception. C'est exactement pour ça qu'ils passent en production.

Vérification 1 : la volumétrie avant et après chaque jointure

Le contrôle qui attrape le plus de bugs, pour le moins d'effort.

avant = len(ventes)
resultat = ventes.merge(referentiel, on="produit_id", how="left")
assert len(resultat) == avant, f"La jointure a change le nombre de lignes : {avant} -> {len(resultat)}"

Mieux, en une option native :

resultat = ventes.merge(referentiel, on="produit_id", how="left", validate="many_to_one")

validate lève une exception si le référentiel contient des clés dupliquées. L'IA ne le met presque jamais spontanément. Ajoutez-le systématiquement.

Vérification 2 : ce que l'agrégation a agrégé

# Ce que l'IA propose
resume = df.groupby("region").sum()

Sur un DataFrame contenant quantite, prix_unitaire, ca et client_id, cette ligne somme aussi les prix unitaires et les identifiants clients. Le résultat existe, il n'a aucun sens.

# Version explicite
resume = df.groupby("region", as_index=False).agg(
    quantite_totale=("quantite", "sum"),
    ca_total=("ca", "sum"),
    nb_clients=("client_id", "nunique"),
)

Règle : jamais de .sum() nu sur un groupby. Nommez chaque agrégat. Le code est plus long et il est juste.

Vérification 3 : les NaN, comptés avant et après

pandas ignore les NaN dans mean(), sum() et la plupart des agrégations. Une moyenne sur une colonne à 40 % de valeurs manquantes ne le signale pas.

print(df.isna().sum())
print(f"{df['marge'].isna().mean():.1%} de valeurs manquantes sur marge")

Si la proportion dépasse quelques pour cent, la question n'est plus technique mais métier : ces lignes doivent-elles être exclues, imputées, ou remontées comme un problème de source ? Une IA ne peut pas trancher ça, parce que la réponse dépend du contexte de l'entreprise.

Vérification 4 : les doublons, sur la vraie clé

cle = ["date", "client_id", "produit_id"]
doublons = df.duplicated(subset=cle).sum()
assert doublons == 0, f"{doublons} doublons sur {cle}"

df.drop_duplicates() sans subset, que l'IA propose volontiers, ne retire que les lignes identiques sur toutes les colonnes. Deux enregistrements du même événement qui diffèrent d'un timestamp de traitement survivent tous les deux.

Vérification 5 : les types après lecture

df = pd.read_csv("ventes.csv")
print(df.dtypes)

Les pièges récurrents sur un CSV :

  • Un code produit 00123 lu comme l'entier 123, ce qui casse la jointure avec le référentiel
  • Une date en object au lieu de datetime64, ce qui fait échouer les filtres temporels sans erreur
  • Un prix "12,50" (virgule française) lu comme du texte, ce qui rend la somme impossible ou concaténante
df = pd.read_csv(
    "ventes.csv",
    dtype={"produit_id": "string", "code_postal": "string"},
    parse_dates=["date"],
    decimal=",",
)

Le code généré par IA lit presque toujours en pd.read_csv(chemin) nu. C'est le point d'entrée de la moitié des anomalies en aval.

Vérification 6 : un ordre de grandeur métier

Le contrôle que seule une personne connaissant l'entreprise peut faire.

print(f"CA total : {df['ca'].sum():,.0f} EUR")
print(f"Nombre de commandes : {len(df):,}")
print(f"Panier moyen : {df['ca'].sum() / df['commande_id'].nunique():,.2f} EUR")

Si le panier moyen sort à 4 EUR alors que l'entreprise vend des machines industrielles, quelque chose est faux en amont. Aucun test unitaire ne remplace ce regard, et aucun modèle ne l'a.

C'est votre valeur ajoutée irréductible face à un générateur de code : vous savez ce qu'un chiffre plausible ressemble.

Vérification 7 : figer le comportement dans un test

Une fois le code validé une fois, verrouillez-le. Sinon la prochaine génération d'IA le réécrira différemment, et vous revaliderez tout.

def test_ca_recalcule_ignore_la_colonne_source():
    df = pd.DataFrame({"quantite": [2], "prix_unitaire": [10.0], "ca": [999.0]})
    assert calculer_ca(df)["ca"].iloc[0] == 20.0

C'est le geste qui change la relation à l'IA : elle génère, vos tests arbitrent. La méthode complète est dans tester du code pandas avec pytest.

La checklist, en une passe

# Contrôle Commande
1 Volumétrie après jointure validate="many_to_one"
2 Agrégats nommés .agg(nom=("col", "sum"))
3 Valeurs manquantes df.isna().mean()
4 Doublons sur la clé métier df.duplicated(subset=cle)
5 Types à la lecture dtype=, parse_dates=, decimal=
6 Ordre de grandeur Comparaison au réel connu
7 Test qui fige la règle pytest

Cinq minutes par script. À comparer au coût d'un chiffre faux présenté en comité.

« Copilot me sort du code qui marche »

Oui, et c'est précisément le problème. Un code qui plante se corrige en dix minutes. Un code qui tourne et se trompe de 12 % sur la marge se découvre trois mois plus tard, quand une décision a déjà été prise dessus.

Le déplacement de compétence est net : l'écriture de pandas se déprécie, la capacité à cadrer, contrôler et verrouiller un traitement prend de la valeur. Les gestes correspondants sont ceux du software engineering : structure, tests, versioning, revue.

Trois points de départ concrets :

La chaîne complète, du code généré au repo production-ready avec CI, c'est l'objet de la formation DataCraft.

Questions fréquentes

Faut-il arrêter d'utiliser l'IA pour écrire du code data ? Non. Le gain de vitesse est réel sur le code de plomberie. Ce qui change, c'est qu'on ne livre pas sans contrôle, exactement comme on ne livre pas un chiffre sans le regarder.

Quel modèle génère le code data le plus fiable ? La question est mal posée : tous produisent du code syntaxiquement correct et sémantiquement incertain, parce qu'aucun ne connaît vos règles métier. Le différenciateur est votre dispositif de vérification, pas le modèle.

Comment relire du code généré qu'on ne comprend pas ? Demandez la version simple avant la version optimisée. Un merge suivi d'un groupby explicite se relit, une chaîne de pipe et de lambdas ne se relit pas. Le code que vous ne pouvez pas relire ne doit pas produire de chiffre officiel.

Livre Business Intelligence avec Python

Approfondir avec mon livre

"Business Intelligence avec Python" - Le guide complet pour maîtriser l'analyse de données

Voir sur Amazon →

Formation recommandée

DataCraft

Du notebook chaotique au repo production-ready : structure, tests, Git, CI. Le software engineering appliqué à la data, sur un fil rouge d'entreprise unique.

Voir la formation →

Ne manque rien de l'actualité data

Rejoins +1000 professionnels qui reçoivent chaque semaine mes analyses, conseils et découvertes data.

S'abonner gratuitement
Prochaine révision : Trimestre prochain