L’IA comme double-programmeur QC en R : peut-elle être le contrôle indépendant ?
Laissez un copilote IA écrire la re-dérivation indépendante en QC par double programmation et diffdf attrape un vrai bug de production — puis voyez le faux rapport propre qui montre pourquoi une IA n’est pas un relecteur indépendant qualifié, et pourquoi un humain est maître de l’approbation
La QC par double programmation valide un jeu de données clinique dérivé en faisant re-dériver ce dernier par un programmeur indépendant à partir de la spécification, puis en comparant les deux avec diffdf. Un copilote IA peut-il être ce second programmeur ? Cette leçon exécute les deux versants de la réponse sur des données pharmaverse publiques. Dans le premier scénario, une re-dérivation rédigée par l’IA attrape un vrai bug de production — un BMI initial qui a oublié d’élever la taille au carré — et diffdf pointe les 254 sujets. Dans le second, une spécification laconique et ambiguë amène le code de production et la QC IA à commettre le même faux pas d’unité, diffdf rapporte « No issues were found! », et ce rapport propre est faux. La limite honnête : une IA peut rédiger du code de QC et être une seconde paire d’yeux utile, mais son indépendance n’est pas garantie et elle ne peut pas porter la responsabilité — un humain est maître de l’approbation de la QC.
Date de publication
2 juillet 2026
Modifié
7 juillet 2026
AstucePoints clés
Un copilote IA peut écrire la re-dérivation indépendante en QC par double programmation. Confiez-lui la même spécification, demandez-lui de re-dériver la variable d’une autre façon, et comparez avec diffdf() — l’IA joue le second programmeur, vite.
Quand les deux dérivations diffèrent réellement, ça marche. Un BMI de production (indice de masse corporelle, le poids en kg divisé par la taille en mètres au carré) qui a oublié d’élever la taille au carré s’exécute proprement et paraît plausible ; la re-dérivation rédigée par l’IA est en désaccord sur les 254 sujets, et diffdf() les nomme tous.
Le hic : une IA n’est pas un second programmeur indépendant. Face à la même spécification laconique et ambiguë, le code de production et la QC IA commettent le même faux pas d’unité — et diffdf() rapporte « No issues were found! ». Un rapport propre entre deux dérivations corrélées n’est pas une validation.
Un faux rapport propre ressemble exactement à un vrai. Seule une re-dérivation vraiment indépendante — celle qui vérifie les métadonnées d’unité que la spécification ambiguë a omises — attrape l’erreur partagée (254 écarts).
L’IA rédige le code de QC ; un humain est maître de la QC. Un copilote IA est une seconde paire d’yeux utile, mais sa sortie est elle-même non qualifiée, son indépendance n’est pas garantie, et elle ne peut pas signer un enregistrement de QC. Le programmeur qualifié est maître du contrôle indépendant et de la responsabilité.
Introduction
La double programmation — aussi appelée programmation indépendante — est la façon dont un jeu de données clinique dérivé gagne la confiance. Un programmeur de production construit le jeu de données qui sera soumis ; un second programmeur indépendant, travaillant à partir de la même spécification mais écrivant son propre code, le re-dérive ; les deux sont comparés, et s’ils concordent, la dérivation est validée. La QC (contrôle qualité) signifie ici exactement cela : une re-dérivation indépendante, pas une revue de code. Les mécanismes de la comparaison sont exposés dans La double programmation en R avec diffdf — clés, tolérance, typage strict, lecture du rapport. Cette leçon ne les réenseigne pas. Elle pose une question différente, plus tranchante : un copilote IA peut-il être ce second programmeur indépendant ?
La réponse est un authentique « oui, et » — oui, elle peut écrire une re-dérivation rapide qui attrape de vrais bugs ; et la propriété même qui fait fonctionner la double programmation — l’indépendance — est la seule chose qu’une IA ne peut pas garantir. Nous exécutons les deux moitiés sur des données pharmaverse publiques, de sorte que chaque ligne diffdf() s’exécute. D’abord une QC IA qui attrape un vrai bug de production. Puis le retournement honnête : un faux rapport propre, où l’IA est d’accord avec une mauvaise réponse aussi sûrement qu’elle le serait avec une bonne.
La tâche de QC : le BMI initial sur ADVS
La variable sous QC est un BMI initial dérivé. Nous le construisons à partir d’ADVS (le jeu de données d’analyse des signes vitaux), un jeu de données BDS (Basic Data Structure — structure de données de base : une ligne par sujet, par paramètre et par visite) qui porte WEIGHT en kilogrammes et HEIGHT en centimètres. Nous prenons l’enregistrement initial de chaque sujet — la ligne marquée ABLFL == "Y" (l’indicateur d’enregistrement initial) — et remettons le poids et la taille côte à côte. La taille initiale est mesurée une seule fois à la sélection, donc elle existe pour 254 des sujets inclus ; c’est là l’ensemble d’analyse.
library(pharmaverseadam)library(dplyr)library(tidyr)data("advs", package ="pharmaverseadam")# Baseline weight + height, one row per subject (ABLFL == "Y")bl <- advs %>%filter(PARAMCD %in%c("WEIGHT", "HEIGHT"), ABLFL =="Y") %>%select(USUBJID, PARAMCD, AVAL) %>%distinct() %>%pivot_wider(names_from = PARAMCD, values_from = AVAL) %>%as.data.frame()nrow(bl) # 254 subjects with a baseline weight and height
La spécification de la dérivation est celle des manuels : BMI = poids (kg) / taille (m)². La taille est enregistrée en centimètres, elle doit donc être divisée par 100 avant d’être élevée au carré. Calculées correctement, les valeurs tombent dans une plage physiologiquement sensée — un fait qu’il vaut la peine de fixer maintenant, car c’est l’ancre de plausibilité sur laquelle les deux scénarios s’appuient :
library(pharmaverseadam)library(dplyr)library(tidyr)data("advs", package ="pharmaverseadam")bl <- advs %>%filter(PARAMCD %in%c("WEIGHT", "HEIGHT"), ABLFL =="Y") %>%select(USUBJID, PARAMCD, AVAL) %>%distinct() %>%pivot_wider(names_from = PARAMCD, values_from = AVAL) %>%as.data.frame()# The correct derivation: kg / m^2, height converted cm -> mcorrect_bmi <- bl$WEIGHT / (bl$HEIGHT /100)^2range(correct_bmi) # roughly 13.7 to 40.2 -- real human BMIs
[1] 13.66745 40.16536
Environ 13.7 à 40.2 — de vrais BMI adultes. Gardez cette plage à l’esprit : une dérivation qui produit des nombres bien en dehors est manifestement fausse, et une qui produit des nombres à l’intérieur peut malgré tout être fausse d’une manière qu’aucun contrôle de plage ne détectera. Les deux pièges arrivent.
Scénario A : la QC IA attrape un vrai bug de production
Ici la spécification est sans ambiguïté : le BMI est le poids en kilogrammes divisé par la taille en mètres au carré ; la taille est en centimètres, donc divisez d’abord par 100. Nous semons un bug de production réaliste — le genre qui survit à un coup d’œil sur la sortie. Le programmeur de production a oublié d’élever la taille au carré :
library(pharmaverseadam)library(dplyr)library(tidyr)data("advs", package ="pharmaverseadam")bl <- advs %>%filter(PARAMCD %in%c("WEIGHT", "HEIGHT"), ABLFL =="Y") %>%select(USUBJID, PARAMCD, AVAL) %>%distinct() %>%pivot_wider(names_from = PARAMCD, values_from = AVAL) %>%as.data.frame()# PRODUCTION (buggy): forgot the exponent -> weight / (height in metres), not squaredprod_bmi <-data.frame(USUBJID = bl$USUBJID, BMI = bl$WEIGHT / (bl$HEIGHT /100))range(prod_bmi$BMI) # 23 to 65 -- LOOKS like a plausible BMI table
[1] 23.09259 65.29281
Voilà pourquoi le bug est dangereux : la sortie erronée va d’environ 23 à 65. Un relecteur qui survole le tableau voit des nombres qui se lisent comme des BMI, et passe à autre chose. L’erreur ne s’annonce pas.
Jouons maintenant l’étape de QC avec un copilote IA. Munie de la même spécification (pas du code de production) et invitée à re-dériver la variable indépendamment, une IA produit la formule directe issue de la spécification : kilogrammes sur mètres au carré. Voici la re-dérivation qu’un copilote IA renvoie à partir de ce prompt :
library(pharmaverseadam)library(dplyr)library(tidyr)data("advs", package ="pharmaverseadam")bl <- advs %>%filter(PARAMCD %in%c("WEIGHT", "HEIGHT"), ABLFL =="Y") %>%select(USUBJID, PARAMCD, AVAL) %>%distinct() %>%pivot_wider(names_from = PARAMCD, values_from = AVAL) %>%as.data.frame()# AI QC re-derivation FROM THE SPEC: kg / m^2, height squaredai_qc <-data.frame(USUBJID = bl$USUBJID, BMI = bl$WEIGHT / (bl$HEIGHT /100)^2)range(ai_qc$BMI) # 13.7 to 40.2 -- the correct range
[1] 13.66745 40.16536
Deux dérivations de la même variable, à partir de la même spécification, écrites par deux « programmeurs » différents — l’un d’eux étant l’IA. La double programmation pose maintenant la seule question qui compte : concordent-elles ? Comparez-les avec diffdf(), en prenant l’identifiant de sujet comme clé pour qu’il apparie par sujet, pas par ordre de ligne.
Differences found between the objects!
Summary of BASE and COMPARE
====================================
PROPERTY BASE COMP
------------------------------------
Name prod_bmi ai_qc
Class data.frame data.frame
Rows(#) 254 254
Columns(#) 2 2
------------------------------------
Not all Values Compared Equal
=============================
Variable No of Differences
-----------------------------
BMI 254
-----------------------------
First 10 of 254 rows are shown in table below
===========================================
VARIABLE USUBJID BASE COMPARE
-------------------------------------------
BMI 01-701-1015 36.94678 25.07927
BMI 01-701-1023 49.39099 30.38324
BMI 01-701-1028 55.87177 31.42394
BMI 01-701-1033 50.46788 28.79600
BMI 01-701-1034 40.40274 26.07638
BMI 01-701-1047 45.17801 30.40447
BMI 01-701-1097 46.19028 27.34609
BMI 01-701-1111 37.84125 23.91384
BMI 01-701-1115 43.46126 23.93110
BMI 01-701-1118 39.49207 21.89868
-------------------------------------------
diffdf() rapporte Differences found between the objects! — chacun des 254 sujets (BMI 254 écarts), les dix premiers étant détaillés : BASE (production) contre COMPARE (la QC IA), valeur par valeur. L’écart — le désaccord entre les deux dérivations — est total, et il pointe droit sur le bug. Le sujet 01-701-1015 affiche 36.9 en production contre 25.1 dans la QC IA ; le nombre de production est celui qui n’est pas au carré. La re-dérivation indépendante rédigée par l’IA a fait exactement ce qu’aurait fait celle d’un programmeur QC : elle a fait remonter une véritable erreur de production qui avait échappé à l’œil.
Corrigez la production — élevez la taille au carré — et relancez la comparaison :
No issues were found! — les deux dérivations indépendantes concordent désormais sur chaque sujet. Dans ce scénario, la QC IA a gagné sa place : une re-dérivation indépendante a attrapé un vrai bug et confirmé le correctif. C’est l’argument pour utiliser une IA comme une seconde paire d’yeux rapide. Voici maintenant l’argument contre le fait de s’y fier.
Scénario B : le faux rapport propre
Les vraies spécifications sont rarement aussi nettes que celle du Scénario A. Supposons que la spécification que le programmeur de production et le programmeur QC reçoivent tous deux soit laconique : « BMI = WEIGHT / HEIGHT². » Aucune clause d’unité. La colonne s’appelle littéralement HEIGHT, et elle contient des centimètres — mais la spécification ne le dit pas, et un programmeur pressé lit la colonne au premier degré comme des mètres. Le code de production commet ce faux pas :
Maintenant la QC IA. Munie de la même spécification laconique et de la même colonne nommée HEIGHT, un copilote IA fait correspondre le motif à la lecture la plus littérale — WEIGHT / HEIGHT² — et commet le faux pas identique. Elle n’a pas plus de raison que l’humain pressé de soupçonner les unités, et elle a été entraînée sur les mêmes conventions que celles qui ont produit la spécification ambiguë au départ :
library(pharmaverseadam)library(dplyr)library(tidyr)data("advs", package ="pharmaverseadam")bl <- advs %>%filter(PARAMCD %in%c("WEIGHT", "HEIGHT"), ABLFL =="Y") %>%select(USUBJID, PARAMCD, AVAL) %>%distinct() %>%pivot_wider(names_from = PARAMCD, values_from = AVAL) %>%as.data.frame()# AI QC: same terse spec, same literal reading of HEIGHT -> the SAME unit slipai_unit <-data.frame(USUBJID = bl$USUBJID, BMI = bl$WEIGHT / (bl$HEIGHT)^2)
Comparez les deux avec diffdf(), exactement comme avant :
No issues were found! — et ce rapport propre est un mensonge. Les deux dérivations sont fausses (chaque BMI vaut environ 0.0025, faux d’un facteur 10 000), mais elles sont fausses de la même manière, si bien que diffdf() ne trouve rien à contredire. C’est le mode de défaillance que la double programmation est censée empêcher : deux implémentations qui partagent une erreur concorderont toujours, et leur concordance ressemble exactement à une vraie validation. Le rapport est, octet pour octet, le même « No issues were found! » que celui que vous avez approuvé dans le Scénario A.
Ce qui l’attrape, c’est une véritable indépendance. Un programmeur QC vraiment indépendant ne se contente pas de retaper la formule laconique — il vérifie la source : HEIGHT dans ADVS est enregistrée en centimètres, elle doit donc être convertie avant d’être élevée au carré. Cette re-dérivation est en désaccord avec l’erreur partagée sur chaque sujet :
Differences found between the objects!
Summary of BASE and COMPARE
====================================
PROPERTY BASE COMP
------------------------------------
Name prod_unit qc_correct
Class data.frame data.frame
Rows(#) 254 254
Columns(#) 2 2
------------------------------------
Not all Values Compared Equal
=============================
Variable No of Differences
-----------------------------
BMI 254
-----------------------------
First 10 of 254 rows are shown in table below
==============================================
VARIABLE USUBJID BASE COMPARE
----------------------------------------------
BMI 01-701-1015 0.002507927 25.07927
BMI 01-701-1023 0.003038324 30.38324
BMI 01-701-1028 0.003142394 31.42394
BMI 01-701-1033 0.002879600 28.79600
BMI 01-701-1034 0.002607638 26.07638
BMI 01-701-1047 0.003040447 30.40447
BMI 01-701-1097 0.002734609 27.34609
BMI 01-701-1111 0.002391384 23.91384
BMI 01-701-1115 0.002393110 23.93110
BMI 01-701-1118 0.002189868 21.89868
----------------------------------------------
diffdf_has_issues() renvoie TRUE, et le rapport nomme les 254 sujets. La différence entre le faux rapport propre du Scénario B et cette vraie prise n’est pas l’outil — diffdf() a fait exactement ce qu’on lui a demandé les deux fois. La différence, c’est l’indépendance : une QC qui partage l’hypothèse du code de production produit un « No issues found » qui ressemble à une validation sans en être une. (suppress_warnings = TRUE empêche seulement l’écart de remonter aussi sous forme d’avertissement R ; le rapport est le même.)
Pourquoi une IA n’est pas un second programmeur indépendant
Le Scénario B n’est pas une bizarrerie liée à un prompt. Il est structurel, et c’est exactement ce contre quoi la discipline met elle-même en garde. Le guide PHUSE sur la QC indépendante est explicite : la prémisse de la double programmation est que deux programmeurs qui créent de façon autonome une sortie identique peuvent être considérés comme corrects — et qu’« il est vital que les programmeurs ne regardent pas le programme de l’autre ». Il avertit aussi que « les spécifications d’un jeu de données peuvent avoir plus d’une interprétation possible » et que, même avec deux programmeurs, « il reste de la place pour l’erreur humaine ». Un copilote IA brise cette prémisse de trois manières concrètes :
Erreurs corrélées. L’hypothèse d’indépendance exige que les erreurs des deux programmeurs soient non corrélées — qu’une mauvaise hypothèse de l’un ait peu de chances d’être partagée par l’autre. Une IA entraînée sur les mêmes conventions et les mêmes motifs ambigus que tout le monde reproduit la lecture la plus courante, qui est précisément celle qu’un programmeur de production pressé a le plus de chances d’avoir utilisée. Les erreurs sont corrélées par construction, et des erreurs corrélées mettent la double programmation en échec (Scénario B).
Fausse concordance silencieuse. L’IA renvoie « la dérivation concorde » avec la même assurance, que la réponse partagée soit juste ou fausse. Elle n’a aucun signal qui distingue une vraie absence d’écart d’une fausse — le rapport propre du Scénario B était aussi calme et complet que celui du Scénario A.
Aucune responsabilité. La double programmation se termine par une approbation : un programmeur nommé et qualifié atteste que le contrôle indépendant a été effectué et réussi, et en répond lors d’un audit. Une IA ne peut pas signer un enregistrement de QC, ne peut pas être le second programmeur responsable, et ne peut pas être tenue responsable d’un chiffre faux qui atteint une soumission.
Le R Validation Hub formule le principe général pour les outils qui sous-tendent ce travail : l’assurance vient d’une validation documentée et portée par un humain, pas de la parole de l’outil lui-même. Un copilote IA se situe à l’intérieur de ce processus comme un rédacteur rapide de code de QC — jamais comme le relecteur indépendant qui le certifie.
Qui est maître de quoi
Alignez les deux scénarios et la frontière est exacte. Dans le Scénario A, le copilote IA a écrit une re-dérivation qui a attrapé un vrai bug de production — un travail authentique et utile, une seconde paire d’yeux rapide. Dans le Scénario B, le même copilote a produit un faux rapport propre, en étant d’accord avec une mauvaise réponse parce qu’il partageait la mauvaise hypothèse. Rien à propos de l’IA n’a changé entre les deux ; ce qui a changé, c’est de savoir si sa dérivation était réellement indépendante de l’erreur de production, et c’est la seule propriété dont dépend la double programmation et que l’IA ne peut pas garantir.
La responsabilité ne bouge donc jamais. Un humain — le programmeur QC qualifié — est maître de la re-dérivation indépendante (y compris du jugement de questionner la spécification et de vérifier les métadonnées d’unité autour desquelles le Scénario B a basculé), est maître de la lecture du rapport diffdf() comme d’une preuve plutôt que d’un verdict, et est maître de l’approbation sur laquelle un régulateur s’appuie. C’est un livrable GxP (les réglementations qualité de « bonnes pratiques » régissant les données cliniques), et valider un jeu de données dérivé signifie une vérification documentée, indépendante et portée par un humain — la norme que le CDISC ADaM (Analysis Data Model, le modèle de données d’analyse) fixe pour les données d’analyse. Une IA peut rédiger le code de QC et accélérer la rédaction ; elle n’est jamais la validation. Dit simplement : utilisez une IA comme une seconde paire d’yeux, jamais comme le relecteur indépendant attitré — et ne lisez jamais un « No issues were found! » de diffdf() comme « validé » quand la même IA a écrit les deux côtés.
🟢 Avec un agent IA
Demandez à Prova« Une IA a écrit ma re-dérivation QC indépendante et diffdf dit “No issues were found!” — comment savoir si ce rapport propre est réel et non une erreur partagée ? » — elle répond en s’appuyant sur les leçons de validation de cette série, avec les contrôles exécutables de double programmation diffdf() et d’indépendance que vous pouvez essayer sur votre propre dérivation. The runtime is the judge.Demandez à Prova →
Problèmes fréquents
Lire « No issues were found! » comme « validé » quand une IA a écrit les deux côtés. Un rapport diffdf() propre signifie seulement que deux dérivations concordent ; il signifie validé uniquement si les deux sont réellement indépendantes. Le Scénario B a produit exactement le même rapport propre à partir de deux dérivations qui partageaient un bug d’unité. Si la même IA (ou la même personne, ou un programme copié) a produit à la fois le code de production et la re-dérivation QC, leur concordance ne porte aucun poids de validation — l’indépendance qui fait fonctionner la double programmation manque. Établissez que le chemin de QC est indépendant avant de vous fier à son rapport propre.
Passer un résultat de pivot_wider() directement à diffdf().pivot_wider() renvoie un tibble, et mêler des entrées tibble et data-frame peut enregistrer de fausses différences de classe. Enveloppez les données remises en forme dans as.data.frame() (comme le fait chaque bloc ici) pour que diffdf() compare des valeurs, pas des types de conteneur. Exécuter distinct() avant le pivot évite aussi les colonnes-listes quand un sujet a plus d’un enregistrement initial.
Oublier keys, de sorte que diffdf() apparie par ordre de ligne. Sans keys = "USUBJID", diffdf() aligne les deux data frames par position ; si la production et la QC ont trié leur sortie différemment, il signale chaque ligne. Prenez toujours pour clé la ou les colonnes qui identifient un sujet de façon unique afin que la comparaison apparie par identité. (Les mécanismes complets — clés non uniques, tolérance, typage strict — sont traités dans La double programmation en R avec diffdf.)
Questions fréquentes
NotePuis-je utiliser l’IA pour la QC par double programmation ?
Comme outil de rédaction, oui — comme relecteur indépendant attitré, non. Un copilote IA peut écrire la re-dérivation QC à partir de la spécification plus vite que vous ne la tapez, et quand sa dérivation diffère réellement de la production, il attrape de vrais bugs (Scénario A ci-dessus). Mais le code de QC de l’IA est lui-même non qualifié, et un humain qualifié doit être maître de l’approbation. Utilisez-le pour rédiger et accélérer le contrôle, jamais pour le certifier.
NoteUne IA est-elle un second programmeur indépendant valide ?
Non. La double programmation fonctionne parce que les deux programmeurs sont indépendants, si bien que leurs erreurs ont peu de chances d’être les mêmes. Une IA entraînée sur les mêmes conventions et les mêmes motifs ambigus que tout le monde tend à reproduire la lecture la plus courante — la même qu’a utilisée un programmeur de production pressé — de sorte que ses erreurs sont corrélées avec celles de la production, ce qui est exactement ce qui casse la méthode (Scénario B). Le guide PHUSE sur la QC indépendante fait de l’indépendance toute la prémisse.
NotePourquoi diffdf a-t-il dit « No issues were found! » alors que les deux dérivations étaient fausses ?
Parce que diffdf() compare deux jeux de données pour vérifier leur concordance ; il ne peut pas savoir si la valeur sur laquelle ils s’accordent est correcte. Quand la production et la QC IA ont commis la même erreur d’unité, leurs sorties étaient identiques, donc diffdf() a correctement rapporté aucune différence — un faux rapport propre. Un rapport propre valide une dérivation seulement quand les deux chemins qui l’ont produite sont réellement indépendants ; une re-dérivation vraiment indépendante qui a vérifié les métadonnées d’unité a été en désaccord sur les 254 sujets.
NoteQui approuve la QC si une IA a écrit le code de QC ?
Un programmeur humain qualifié, toujours. La re-dérivation de l’IA est un brouillon non qualifié ; un programmeur QC nommé la relit, confirme qu’elle est réellement indépendante de la logique de production, lit le rapport diffdf() comme une preuve, et atteste du résultat dans la piste d’audit. La responsabilité d’une valeur dérivée qui atteint une soumission ne se transfère jamais à l’outil — c’est la frontière que la SOP d’IA auditable pour la programmation clinique formalise.
Les mécanismes sont le même appel diffdf(base, compare, keys = ...) enseigné dans La double programmation en R avec diffdf. Ce qui change ici, c’est qui écrit la seconde dérivation et ce que vaut sa concordance. Quand une IA écrit le côté QC, un rapport diffdf() propre peut être un faux rapport propre, parce que l’IA peut partager l’hypothèse de la production. La leçon porte sur l’indépendance que le rapport suppose silencieusement, pas sur la comparaison elle-même.
Testez vos connaissances
ImportantÀ vous : ce rapport propre est-il réel ?
Un collègue fait la QC d’une variable BMI dérivée en demandant à un copilote IA de la re-dériver à partir de la même spécification d’une ligne qu’a utilisée le programmeur de production, puis exécute diffdf(prod, ai_qc, keys = "USUBJID") et obtient No issues were found!. Il marque la variable comme validée.
En prose : expliquez l’unique condition sous laquelle ce rapport propre valide bien la dérivation, et l’unique condition sous laquelle il ne la valide pas — et pourquoi le rapport paraît identique dans les deux cas.
En R : construisez un petit exemple à deux sujets où HEIGHT est en centimètres, écrivez un prod et un ai_qc de BMI qui oublient tous deux la conversion /100, confirmez que diffdf() ne rapporte aucun écart, puis ajoutez une re-dérivation vraiment indépendante qui convertit les unités et montrez qu’elle est en désaccord.
AstuceIndice
diffdf() teste si deux dérivations concordent, pas si elles sont correctes. Le rapport propre valide uniquement si prod et ai_qc sont réellement indépendants ; s’ils partagent la même mauvaise hypothèse (la conversion d’unité manquante), ils concordent et le rapport est un faux rapport propre. Une troisième dérivation qui divise HEIGHT par 100 avant de l’élever au carré sera en désaccord avec les deux.
AstuceSolution
Étape 1. Le rapport propre valide la dérivation uniquement si les dérivations de production et de QC sont indépendantes — écrites à partir de la spécification sans partage de code ni d’hypothèses — de sorte qu’une erreur partagée soit peu probable. Il ne valide pas quand les deux chemins sont corrélés (ici, la même IA, ou la même mauvaise lecture littérale d’une spécification ambiguë, a produit les deux) : ils commettent l’erreur identique, concordent exactement, et diffdf() rapporte « No issues were found! » — un faux rapport propre qui est, octet pour octet, identique à un vrai. Le rapport ne peut pas vous dire lequel c’est ; seul le fait de savoir que le chemin de QC est réellement indépendant le peut.
library(diffdf)bl <-data.frame(USUBJID =c("01-001", "01-002"),WEIGHT =c(70, 90), # kgHEIGHT =c(175, 180) # cm -- must be /100 before squaring)# prod and ai_qc share the same unit bug (no /100 conversion)prod <-data.frame(USUBJID = bl$USUBJID, BMI = bl$WEIGHT / (bl$HEIGHT)^2)ai_qc <-data.frame(USUBJID = bl$USUBJID, BMI = bl$WEIGHT / (bl$HEIGHT)^2)diffdf(prod, ai_qc, keys ="USUBJID") # "No issues were found!" -- FALSE clean# a truly independent re-derivation that checks the units (HEIGHT is cm)qc_correct <-data.frame(USUBJID = bl$USUBJID, BMI = bl$WEIGHT / (bl$HEIGHT /100)^2)diffdf_has_issues(diffdf(prod, qc_correct, keys ="USUBJID", suppress_warnings =TRUE)) # TRUE
Le premier diffdf() est propre parce que les deux dérivations partagent le bug ; l’indépendant signale les deux sujets. Même outil, verdicts opposés — la différence, c’est l’indépendance, pas diffdf().
NoteVérification rapide : un copilote IA a écrit la re-dérivation QC indépendante, et diffdf() face au jeu de données de production rapporte « No issues were found! ». La variable est-elle validée ?
A. Oui — deux dérivations ont concordé, ce qu’exige la double programmation. B. Pas nécessairement — si l’IA partage l’hypothèse de la production, les deux peuvent être fausses de la même manière et concorder, de sorte que le rapport propre peut être un faux rapport propre ; un humain qualifié doit confirmer que la QC était réellement indépendante et être maître de l’approbation. C. Oui, du moment qu’un modèle actuel et capable a écrit le code de QC.
AstuceAfficher la réponse
B. La double programmation ne valide que lorsque les deux dérivations sont indépendantes. Une IA peut reproduire la même mauvaise hypothèse que la production (erreurs corrélées), auquel cas les deux concordent et diffdf() rapporte « No issues were found! » pour un bug partagé — un faux rapport propre identique à un vrai, ce qui explique pourquoi A est faux. La capacité du modèle ne crée pas d’indépendance (ce qui écarte C) ; seul un humain qualifié qui confirme que le chemin de QC est réellement indépendant, et qui est maître de l’approbation, fait du rapport propre une validation.
Conclusion
Un copilote IA peut jouer le second programmeur dans la QC par double programmation, et le Scénario A en montre le bon côté : munie de la spécification, elle a écrit une re-dérivation indépendante qui a attrapé un vrai bug de production — un BMI initial qui a oublié d’élever la taille au carré — et diffdf() a nommé les 254 sujets. C’est une seconde paire d’yeux rapide et utile. Mais le Scénario B montre la frontière qui ne bouge jamais : munie d’une spécification laconique et ambiguë, l’IA a commis le même faux pas d’unité que la production, diffdf() a rapporté un « No issues were found! » propre, et ce rapport propre était faux. La propriété dont dépend la double programmation — l’indépendance — est celle qu’une IA ne peut pas garantir, parce que ses erreurs sont corrélées avec les conventions que tout le monde partage. Une IA rédige donc le code de QC ; un humain qualifié est maître du contrôle indépendant, lit le rapport comme une preuve, et approuve. L’IA change la vitesse du brouillon de QC. Elle ne change rien à qui est responsable du chiffre. The runtime is the judge.
Note
Cette leçon est reproductible : la tâche de QC, le bug du Scénario A et sa prise, le faux rapport propre du Scénario B, et la re-dérivation vraiment indépendante qui l’expose se reproduisent tous ici sur des données pharmaverse publiques. Copiez n’importe quel bloc et exécutez-le pour les reproduire. L’étape de rédaction par l’IA se fait dans votre propre outillage ; le R qui réalise et teste la QC est réel et s’exécute. The runtime is the judge.
Où cela s’inscrit : c’est l’instance QC de la série de programmation clinique agentique — un copilote IA placé dans le siège du validateur, où son utilité (Scénario A) et sa limite structurelle (Scénario B) sont toutes deux visibles. Elle retourne la discipline rédiger-puis-valider de la série sur l’étape de validation elle-même.
Cette page vous a-t-elle été utile ?
Merci pour votre retour !
Recevez les nouvelles leçons R & Python par e-mail
Pratique, reproductible, sans spam. Désinscription à tout moment.
Double opt-in. Nous ne partageons jamais votre e-mail.
@online{2026,
author = {},
title = {L’IA comme double-programmeur QC en R : peut-elle être le
contrôle indépendant\,?},
date = {2026-07-02},
url = {https://www.datanovia.com/learn/pharma-clinical/08-agentic-clinical-programming/ai-as-qc-double-programmer},
langid = {fr}
}