
L’IA pour la programmation clinique en R : ce qui marche, ce qui échoue
Sachez exactement où un copilote IA vous fait gagner un temps réel et où il vous livrera une réponse assurée mais fausse — puis faites de la barrière « valider avant d’utiliser » ce qui les distingue
Une carte honnête des capacités pour utiliser un copilote IA (Claude, ChatGPT, GitHub Copilot) en programmation R d’essais cliniques. Voyez là où il aide vraiment — rédiger du code standard admiral/xportr, traduire une dérivation écrite, expliquer une erreur obscure, QC de premier passage — et là où il échoue dangereusement : inventer des règles CDISC et de la terminologie contrôlée, et des erreurs de logique silencieuses comme une jointure interne par défaut qui supprime discrètement des lignes. Une démo exécutable laisse un merge rédigé par l’IA corrompre le dénominateur d’une population de sécurité, puis une barrière QC indépendante avec diffdf l’attrape. Le principe : le code rédigé par l’IA est non qualifié jusqu’à ce qu’il franchisse les mêmes barrières de validation que celui d’un humain — l’IA change la vitesse du premier brouillon, jamais la responsabilité.
- Un copilote IA est un rédacteur rapide, pas un auteur validé. Il peut transformer une spécification en code R en quelques secondes — mais une soumission est un livrable GxP (les réglementations qualité « bonnes pratiques » : GCP, GMP, GLP), et aucun brouillon ne porte de statut de validation tant qu’un humain qualifié ne lui a pas fait franchir les mêmes barrières que tout code doit franchir.
- Utilisez l’IA là où une erreur est peu coûteuse à détecter. Le code standard, les refactorisations, les docstrings, les explications d’erreurs, la traduction d’une spécification en code et les squelettes de tests sont des usages à faible risque et forte valeur — la revue attrape les erreurs immédiatement.
- Méfiez-vous-en là où une erreur est un chiffre faux. Les règles CDISC et la terminologie contrôlée inventées, le choix de la méthode statistique et les erreurs de logique silencieuses (une jointure interne par défaut, la gestion des
NA, une borne<au lieu de<=) produisent une sortie plausible, assurée et fausse qu’un coup d’œil ne détectera pas. - La démo ci-dessous est tout l’argument. Un
merge()rédigé par l’IA s’exécute proprement et sous-estime silencieusement le décompte de sécurité de chaque bras de traitement ; une re-dérivation QC indépendante etdiffdf()l’attrapent. S’exécuter n’est pas la même chose qu’être correct. - L’IA change la vitesse, pas la responsabilité. Le programmeur et le promoteur restent redevables de chaque valeur dérivée. La barrière ne bouge pas parce que le premier brouillon provient d’un modèle.
Introduction
Un copilote IA — un assistant de codage IA tel que Claude, ChatGPT ou GitHub Copilot — rédigera du code R clinique plus vite que vous ne le tapez. Demandez un décompte de sujets par bras joignant deux jeux de données et vous obtenez en quelques secondes une réponse syntaxiquement parfaite. La tentation est évidente, et le piège aussi : une soumission clinique est un livrable GxP (les réglementations qualité « bonnes pratiques » — GCP, GMP, GLP), et « le code s’est exécuté » n’a jamais été le critère pour présenter un chiffre à un régulateur.
La question honnête n’est donc pas « l’IA est-elle assez bonne ? » — c’est « à quoi pouvez-vous réellement vous fier, et que ne devez-vous jamais prendre pour argent comptant ? » Cette leçon y répond avec une carte des capacités concrète, un unique principe directeur et une démo exécutable où une ligne de code rédigée par l’IA est discrètement, dangereusement fausse. C’est la leçon d’ouverture de cette série et le complément d’une SOP d’IA auditable, la procédure opératoire normalisée qui transforme le principe posé ici en un flux de travail documenté, du prompt à l’approbation. Là où cette leçon vous donne la gouvernance, celle-ci vous donne la carte — et vous montre un bug que la barrière attrape.
Cet écart, c’est la leçon en une figure : le code rédigé par l’IA a produit les barres orange sans la moindre erreur ni avertissement, et chacune est un dénominateur faux pour un tableau de sécurité. Nous le construisons, l’attrapons et le corrigeons ci-dessous.
Ce que l’IA fait bien, et là où elle est dangereuse
Commencez par une carte honnête. La distinction ne porte pas sur l’intelligence du modèle — les assistants modernes écrivent du R compétent. Elle porte sur le risque résiduel : à quel point un brouillon plausible mais faux vous nuit s’il passe au travers, et avec quelle facilité vous pouvez l’attraper.
Usages solides — faible risque résiduel, faciles à vérifier
Ce sont de véritables gains de temps. Une erreur ici est évidente ou attrapée immédiatement à la relecture, alors laissez l’assistant faire la frappe.
| Là où l’IA aide | Pourquoi c’est un bon usage | Comment vous le vérifiez tout de même |
|---|---|---|
Rédiger du code standard admiral / xportr à partir d’une spécification écrite |
Code répétitif et bien balisé que le modèle a vu des milliers de fois | Relisez-le au regard de la spécification ; exécutez-le |
| Traduire une règle de dérivation écrite en R | Correspondance mécanique de la prose vers le code | Comparez la logique du code à la règle, ligne par ligne |
| Expliquer une erreur obscure ou la fonction de quelqu’un d’autre | Rapide, contextuel, généralement correct sur les erreurs courantes | Vérifiez que le correctif la résout réellement |
Refactoriser, commenter et ajouter de la documentation roxygen |
Cosmétique et structurel — le comportement ne devrait pas changer | Relancez les tests ; confirmez que la sortie est inchangée |
| Esquisser des tests unitaires et suggérer des contrôles QC | Vous donne un squelette de départ à relire et étendre | Relisez chaque test ; ajoutez à la main les cas qu’il a manqués |
| Revue de code de premier passage — repérer les défauts évidents | Une paire d’yeux supplémentaire peu coûteuse avant une revue humaine | Traitez-la comme un indice, pas comme un feu vert |
Usages faibles et dangereux — fort risque résiduel, plausiblement faux
Ici, le mode de défaillance n’est pas un plantage que vous remarqueriez ; c’est une réponse assurée, d’apparence correcte, qui est fausse pour votre étude. Soyez le plus sceptique précisément là où le coût de l’erreur est le plus élevé.
| Là où l’IA est dangereuse | Pourquoi elle échoue |
|---|---|
| Énoncer les règles CDISC (Clinical Data Interchange Standards Consortium) issues de SDTMIG / ADaMIG (les guides d’implémentation de SDTM — Study Data Tabulation Model — et d’ADaM — Analysis Data Model) | Elle inventera des règles standard plausibles et des valeurs de CT (terminologie contrôlée) avec une confiance totale — et se trompera |
| Erreurs de logique et de cas limites silencieuses | Une jointure interne par défaut qui supprime des lignes, des NA mal gérés, un < là où la spécification dit <= — le code s’exécute et le chiffre est discrètement faux |
| Fabriquer des arguments de fonction ou des citations | Elle appellera un argument qui n’existe pas, ou citera une section de recommandation qui n’a jamais été écrite |
| Assurée mais fausse sur les spécificités réglementaires | Les dates, les exigences et « ce que la FDA exige » sont exactement là où l’hallucination est la plus coûteuse et la plus difficile à repérer |
| Choisir une méthode ou un modèle statistique | Un dactylographe compétent et un piètre méthodologiste — elle recommandera une méthode plausible mais inappropriée pour votre plan |
| Être responsable | Elle ne peut pas relire, ne peut pas signer un enregistrement de validation et ne peut pas répondre d’un résultat faux — la responsabilité ne se transfère jamais à l’outil |
Le principe — ce qui change vraiment quand l’IA rédige le code
Alignez les deux colonnes et toute l’idée de gouvernance s’impose : rien à votre validation ne change. Le brouillon a un nouvel auteur ; la barrière est identique.
| La question que pose la barrière | La réponse — identique que ce soit l’IA ou un humain qui a rédigé |
|---|---|
| Un humain qualifié doit-il relire et justifier chaque ligne ? | Oui. |
| Doit-il franchir les mêmes barrières de QC (contrôle qualité) — double programmation, assertions, tests, reproductibilité ? | Oui. |
| Qui est responsable d’une valeur dérivée fausse ? | Le programmeur et le promoteur — jamais l’outil. |
| Qu’est-ce que l’usage de l’IA change réellement ? | La vitesse du premier brouillon. Rien d’autre. |
Valider avant d’utiliser
Ce dernier tableau, c’est la règle en un mot : non qualifié. Le code rédigé par l’IA n’a aucun statut de validation propre. Il entre dans votre processus exactement là où le premier brouillon non testé d’un programmeur junior entrerait — comme un travail à relire, non comme un résultat à croire — et il gagne sa validation seulement en franchissant les mêmes barrières que tout code franchit : un humain qualifié relit et comprend chaque ligne, puis le code franchit une double programmation indépendante, des assertions défensives, un environnement reproductible et des tests.
C’est libérateur, pas restrictif. Vous n’avez pas besoin d’une « méthodologie de validation de l’IA » spéciale. Vous devez faire passer les brouillons d’IA par la discipline de QC que vous appliquez déjà — et, conformément à une SOP d’IA auditable, consigner que vous l’avez fait. Le reste de cette leçon rend le propos concret : une véritable ligne rédigée par l’IA qui s’exécute parfaitement et est dangereusement fausse, et la barrière qui les distingue.
La barrière en action : attraper une perte de lignes silencieuse
Prenez une tâche qu’un assistant traite en permanence : rapporter le nombre de sujets par bras de traitement dans la population de sécurité, en joignant les données au niveau sujet à un indicateur « tout événement indésirable ». Nous utilisons des données de test publiques du pharmaverse — le ADSL (le jeu de données d’analyse au niveau sujet, une ligne par sujet) et ADAE (le jeu de données d’analyse des événements indésirables) de pharmaverseadam.
L’IA rédige la jointure évidente avec merge(). Observez la valeur par défaut.
library(pharmaverseadam)
data("adsl", package = "pharmaverseadam")
data("adae", package = "pharmaverseadam")
# The safety population: SAFFL is the safety-population flag; TRT01A is the actual treatment arm
saf <- adsl[adsl$SAFFL == "Y", c("USUBJID", "TRT01A")]
# An "any adverse event" flag — one row per subject who had at least one AE
ae_any <- data.frame(USUBJID = unique(adae$USUBJID), ANYAE = "Y",
stringsAsFactors = FALSE)
# The AI-drafted line: a default merge() — which is a SILENT INNER JOIN
ai_merged <- merge(saf, ae_any, by = "USUBJID")
ai_counts <- as.data.frame(table(TRT01A = ai_merged$TRT01A))
names(ai_counts)[2] <- "N"
ai_counts TRT01A N
1 Placebo 69
2 Xanomeline High Dose 70
3 Xanomeline Low Dose 86
cat("Safety population (ADSL, SAFFL=Y):", nrow(saf), "subjects\n")Safety population (ADSL, SAFFL=Y): 254 subjects
cat("Rows after the AI merge: ", nrow(ai_merged), "subjects\n")Rows after the AI merge: 225 subjects
cat("Silently dropped by inner join: ", nrow(saf) - nrow(ai_merged), "subjects\n")Silently dropped by inner join: 29 subjects
Lisez la sortie. Le code s’est exécuté sans erreur, a produit un tableau par bras net, et il est faux. merge() adopte par défaut une jointure interne, il n’a donc conservé que les sujets de sécurité présents dans les données d’événements indésirables — supprimant silencieusement les 29 sujets qui n’ont eu aucun événement indésirable. Ces sujets appartiennent au dénominateur de la population de sécurité ; les décomptes de l’IA (69, 70, 86) sous-estiment chaque bras. Rien ne l’a signalé. Il n’y a aucune erreur à voir, aucun avertissement à écouter — juste un tableau plausible avec les mauvais chiffres derrière une analyse de sécurité.
Passons à la barrière. Un programmeur QC indépendant, travaillant à partir de la même intention, re-dérive les décomptes avec une jointure gauche explicite — en gardant chaque sujet de sécurité et en remplissant un indicateur manquant par "N" — puis compare les deux tableaux avec diffdf(), le moteur de double programmation vu plus tôt dans cette série.
library(pharmaverseadam)
library(diffdf)
data("adsl", package = "pharmaverseadam")
data("adae", package = "pharmaverseadam")
saf <- adsl[adsl$SAFFL == "Y", c("USUBJID", "TRT01A")]
ae_any <- data.frame(USUBJID = unique(adae$USUBJID), ANYAE = "Y",
stringsAsFactors = FALSE)
# The AI draft again (the default inner join) ...
ai_counts <- as.data.frame(table(TRT01A = merge(saf, ae_any, by = "USUBJID")$TRT01A))
names(ai_counts)[2] <- "N"
# ... vs an independent QC re-derivation with an explicit LEFT join
qc_merged <- merge(saf, ae_any, by = "USUBJID", all.x = TRUE)
qc_merged$ANYAE[is.na(qc_merged$ANYAE)] <- "N"
qc_counts <- as.data.frame(table(TRT01A = qc_merged$TRT01A))
names(qc_counts)[2] <- "N"
# The gate: compare the two per-arm counts on the treatment-arm key
diffdf(ai_counts, qc_counts, keys = "TRT01A")Differences found between the objects!
Summary of BASE and COMPARE
====================================
PROPERTY BASE COMP
------------------------------------
Name ai_counts qc_counts
Class data.frame data.frame
Rows(#) 3 3
Columns(#) 2 2
------------------------------------
Not all Values Compared Equal
=============================
Variable No of Differences
-----------------------------
N 3
-----------------------------
=================================================
VARIABLE TRT01A BASE COMPARE
-------------------------------------------------
N Placebo 69 86
N "Xanomeline High Dose" 70 72
N "Xanomeline Low Dose" 86 96
-------------------------------------------------
diffdf() signale trois différences dans N — une par bras. Le brouillon de l’IA (étiqueté BASE) sous-compte chaque bras par rapport à la population de sécurité correcte (COMPARE) : 69 contre 86, 70 contre 72, 86 contre 96. Ni une exécution propre ni un coup d’œil rapide ne l’ont attrapé ; la barrière indépendante, si. C’est tout l’argument en une seule sortie : s’exécuter n’est pas la même chose qu’être correct, et la barrière est ce qui les distingue.
Corrigez la jointure et la barrière le confirme :
library(pharmaverseadam)
library(diffdf)
data("adsl", package = "pharmaverseadam")
data("adae", package = "pharmaverseadam")
saf <- adsl[adsl$SAFFL == "Y", c("USUBJID", "TRT01A")]
ae_any <- data.frame(USUBJID = unique(adae$USUBJID), ANYAE = "Y",
stringsAsFactors = FALSE)
# The fix: an explicit LEFT join keeps every safety subject
ai_fixed <- merge(saf, ae_any, by = "USUBJID", all.x = TRUE)
ai_fixed$ANYAE[is.na(ai_fixed$ANYAE)] <- "N"
fixed_counts <- as.data.frame(table(TRT01A = ai_fixed$TRT01A))
names(fixed_counts)[2] <- "N"
# The independent QC counts, re-derived
qc_merged <- merge(saf, ae_any, by = "USUBJID", all.x = TRUE)
qc_merged$ANYAE[is.na(qc_merged$ANYAE)] <- "N"
qc_counts <- as.data.frame(table(TRT01A = qc_merged$TRT01A))
names(qc_counts)[2] <- "N"
diffdf(fixed_counts, qc_counts, keys = "TRT01A")No issues were found!
« No issues were found! » — la dérivation corrigée correspond désormais exactement à la dérivation QC indépendante. Ce n’est qu’à ce point, le code compris et la barrière au vert, que la dérivation est qualifiée. La leçon n’est pas que l’IA n’est pas digne de confiance ; c’est que la confiance se gagne à la barrière, de la même manière que pour tout code. The runtime is the judge.
Les cadres : un principe, pas une permission
Aucun régulateur n’a publié de règle intitulée « comment utiliser un copilote IA pour écrire du code clinique ». Ce qui existe, ce sont des cadres de plus haut niveau dont les principes s’appliquent — et être précis sur ce que chacun couvre et ne couvre pas fait lui-même partie du refus de la surenchère.
Le cadre provisoire de l’IA de la FDA — une direction, pas un mandat pour les assistants de code. En janvier 2025, la FDA a publié sa première recommandation provisoire sur l’IA dans le développement du médicament, Considerations for the Use of Artificial Intelligence To Support Regulatory Decision-Making for Drug and Biological Products (la période de commentaires s’est close en avril 2025). Deux points à préciser : c’est une recommandation provisoire — elle propose un cadre de crédibilité fondé sur le risque lié au contexte d’utilisation d’un modèle, elle ne l’exige pas — et son sujet est un modèle d’IA qui produit des preuves appuyant une décision réglementaire (par exemple, un modèle prédisant un critère clinique), ce qui est distinct d’un assistant d’IA qui rédige un code qu’un humain valide ensuite. Ce que vous empruntez, c’est le principe — un effort de validation proportionnel au risque, et un humain responsable du résultat — pas une obligation directe.
GAMP 5 — valider l’outil logiciel, selon le risque. Le standard de facto pour la validation des systèmes informatisés (le GAMP 5: A Risk-Based Approach to Compliant GxP Computerized Systems de l’ISPE, 2ᵉ édition) cadre la validation comme un effort proportionnel au risque. Un assistant de codage IA est, au sens de GAMP, un outil utilisé pour produire un livrable ; vous assurez le livrable — le code — au regard de son usage prévu avec un effort proportionné à son risque. Le GAMP Guide: Artificial Intelligence dédié de l’ISPE (2025) étend cela aux systèmes basés sur l’IA dans les contextes GxP.
Le R Validation Hub — la même logique pour les packages R. Le R Validation Hub inter-industriel traite la confiance dans un package comme une activité fondée sur le risque : évaluer le risque d’un composant, puis appliquer une preuve proportionnée. Le code R rédigé par IA est un composant de plus auquel vous appliquez exactement ce prisme.
Les trois convergent vers les mêmes gestes : évaluer le risque, le maîtriser par une validation proportionnée, et garder un humain responsable. Aucun ne dit que le code est digne de confiance parce qu’une IA l’a écrit — et vous ne devriez pas le dire non plus. Pour être direct sur les mots que l’on détourne : assisté par l’IA n’est pas validé par l’IA. Il n’existe pas d’« IA approuvée par la FDA » pour rédiger vos dérivations, aucun pourcentage d’exactitude qui qualifie sa sortie, et aucun modèle dont vous pourriez livrer le code sans relecture. L’IA change la vitesse du premier brouillon. Elle ne change rien à qui répond du résultat.
Demandez à Prova « J’ai utilisé un copilote IA pour rédiger un décompte de sécurité par bras qui joint ADSL à ADAE — comment le mettre en QC pour qu’une jointure interne silencieuse ou une population perdue ne puisse pas corrompre le dénominateur ? » — elle répond en s’appuyant sur les leçons de validation de cette série, avec la double programmation diffdf() exécutable et les contrôles de décompte de lignes que vous pouvez essayer sur le brouillon. The runtime is the judge. Demandez à Prova →
Problèmes fréquents
« Le code s’est exécuté, donc c’est bon. » C’est l’instinct le plus dangereux avec le code généré par IA. S’exécuter sans erreur signifie que la syntaxe est valide, rien de plus. Le bug de jointure interne ci-dessus s’est exécuté parfaitement et a renvoyé un tableau net avec les mauvais chiffres. Une exécution propre est le début de la validation, jamais sa fin — seules les barrières (revue, double programmation, assertions, tests) qualifient la sortie.
L’IA énonce une règle CDISC ou une valeur de terminologie contrôlée avec une confiance totale. Un assistant vous dira l’exigence SDTMIG exacte, la bonne valeur de codelist CT ou la règle de nommage ADaMIG dans une phrase fluide et autoritaire — et se trompera, sans le moindre signe. Ne prenez jamais une affirmation sur un standard ou une terminologie contrôlée d’un modèle pour argent comptant ; vérifiez-la au regard du guide d’implémentation ou de la codelist réellement publiés avant qu’elle ne touche votre code.
Erreurs de logique silencieuses qui survivent à un regard distrait. La jointure interne par défaut fait partie d’une famille : un < là où la spécification dit <=, un NA non géré qui supprime ou mal classe un sujet, une clé de jointure avec doublons qui démultiplie les lignes. Aucune ne plante. Toutes produisent une réponse plausible. C’est précisément pourquoi une re-dérivation indépendante plus diffdf() — et non une relecture du même brouillon — est le contrôle qui les attrape.
Questions fréquentes
Oui — comme outil de rédaction, pas comme source de code validé. Un copilote IA peut rédiger du code R pour une analyse clinique (une dérivation admiral, une étape xportr, un contrôle QC), mais ce brouillon est non qualifié : un humain qualifié doit relire et comprendre chaque ligne, et le code doit ensuite franchir les mêmes barrières de validation que tout code franchit — double programmation indépendante, assertions défensives, reproductibilité et tests. Utilisé de cette manière, il accélère la rédaction sans affaiblir la validation.
Il n’existe aucune règle qui l’interdit ni aucune qui l’adoube. Ce qui compte est la même chose qui a toujours compté : l’analyse est validée et un humain qualifié en est responsable. La recommandation provisoire de la FDA sur l’IA de janvier 2025 propose un cadre de crédibilité fondé sur le risque, mais elle traite des modèles d’IA qui produisent des preuves, non des assistants de codage — et elle est provisoire, non définitive. Pour le code rédigé par IA, appliquez votre discipline habituelle de validation des systèmes informatisés et de QC au code lui-même ; la source du premier brouillon ne change pas ce que la soumission exige.
Elle ne peut pas être responsable, et on ne peut lui faire confiance sur rien de ce qu’elle peut énoncer avec assurance mais se tromper : les règles CDISC/SDTMIG/ADaMIG et les valeurs de terminologie contrôlée, le choix de la méthode statistique pour votre plan, et les erreurs de logique ou de cas limites silencieuses (une jointure interne par défaut, la gestion des NA, une borne < au lieu de <=). Elle ne peut pas non plus signer un enregistrement de validation. Gardez la décision de méthode et chaque spécificité réglementaire avec un humain qualifié, et validez chaque brouillon avant de l’utiliser.
Exactement comme vous validez tout code — la source du brouillon est sans importance pour la barrière. Un programmeur qualifié relit et justifie chaque ligne au regard de la spécification, puis le code franchit une double programmation indépendante (une seconde dérivation distincte comparée avec diffdf()), des assertions défensives, un environnement reproductible et des tests. Pour une jointure comme celle ci-dessus, ajoutez une réconciliation du décompte de lignes pour qu’une population silencieusement perdue échoue bruyamment au lieu de sous-estimer un dénominateur.
Non. La responsabilité ne se transfère jamais à l’outil. Le programmeur qui a utilisé l’assistant, et le promoteur, restent redevables de chaque valeur dérivée — tout comme ils le seraient pour du code tapé à la main. L’IA change la vitesse du premier brouillon et rien à qui répond du résultat.
Testez vos connaissances
Un assistant rédige un décompte par bras de la population de sécurité en joignant un jeu de données au niveau sujet à un indicateur « tout événement indésirable » avec un merge(saf, ae_any, by = "USUBJID") par défaut. Il s’exécute proprement et renvoie un tableau net. À votre insu, la jointure interne par défaut a supprimé chaque sujet de sécurité sans événement indésirable, sous-estimant le dénominateur de chaque bras.
- En prose : nommez la barrière de QC qui attraperait cela avant sa livraison, et expliquez pourquoi « le code s’est exécuté » et « le tableau a l’air correct » ne prouvent pas qu’il est correct.
- En R : construisez un minuscule exemple à deux sujets où un sujet n’a aucun indicateur d’événement indésirable correspondant, dérivez la version IA (
merge()par défaut) et une version QC indépendante (all.x = TRUE,NArempli par"N"), et utilisez un contrôle du décompte de lignes plusdiffdf()pour attraper l’écart.
La barrière qui attrape est la double programmation indépendante : un programmeur QC re-dérive les décomptes à partir de la même intention avec une jointure gauche explicite, puis compare avec diffdf(). Une première alarme peu coûteuse est une réconciliation du décompte de lignes — après la jointure, le nombre de lignes devrait toujours égaler la population de sécurité ; s’il a diminué, la jointure a supprimé des sujets. « Le code s’est exécuté » signifie seulement que la syntaxe est valide.
Étape 1. La barrière est la double programmation indépendante avec diffdf() : un second programmeur re-dérive les décomptes par bras à partir de la même intention — en utilisant une jointure gauche explicite pour que chaque sujet de sécurité soit gardé — et compare les deux tableaux. Une réconciliation du décompte de lignes est l’alerte précoce peu coûteuse : les données jointes devraient toujours avoir une ligne par sujet de sécurité, donc nrow(after) < nrow(saf) signifie que la jointure a silencieusement supprimé des lignes. « Le code s’est exécuté » signifie seulement que la syntaxe est valide ; la version à jointure interne s’exécute parfaitement et est fausse pour chaque sujet qui n’a eu aucun événement indésirable.
library(diffdf)
# Two safety subjects; subject 01-002 has NO adverse event
saf <- data.frame(USUBJID = c("01-001", "01-002"), TRT01A = c("Placebo", "Placebo"))
ae_any <- data.frame(USUBJID = "01-001", ANYAE = "Y") # only 01-001 had an AE
# AI draft: default inner join silently drops 01-002
ai <- merge(saf, ae_any, by = "USUBJID")
stopifnot(nrow(ai) == nrow(saf)) # FAILS — the row-count alarm fires
# Independent QC: explicit left join keeps every safety subject
qc <- merge(saf, ae_any, by = "USUBJID", all.x = TRUE)
qc$ANYAE[is.na(qc$ANYAE)] <- "N"
ai_counts <- as.data.frame(table(TRT01A = ai$TRT01A)); names(ai_counts)[2] <- "N"
qc_counts <- as.data.frame(table(TRT01A = qc$TRT01A)); names(qc_counts)[2] <- "N"
diffdf(ai_counts, qc_counts, keys = "TRT01A") # Placebo: BASE 1 vs COMPARE 2Le contrôle du décompte de lignes stopifnot() échoue immédiatement, et diffdf() signale le bras — la revue l’explique ensuite, et la jointure est corrigée avant que la dérivation ne soit qualifiée.
A. Validée — elle s’est exécutée sans erreur et le tableau a l’air correct. B. Non qualifiée — tant qu’un humain ne l’a pas relue et qu’elle n’a pas franchi les barrières de QC (double programmation, assertions, tests), elle n’a aucun statut de validation. C. Validée, à condition que l’assistant soit un modèle actuel et performant.
B. S’exécuter proprement et avoir l’air correct ne prouvent pas l’exactitude — le brouillon à jointure interne a fait les deux et a silencieusement sous-estimé chaque dénominateur. La sortie d’une IA est un brouillon non qualifié quel que soit le modèle qui l’a produit (ce qui écarte C) ; elle gagne sa validation seulement par une revue humaine plus les mêmes barrières de QC que tout code doit franchir (ce qui écarte A).
Conclusion
Un copilote IA est un véritable accélérateur pour la programmation clinique en R — tant que vous êtes honnête sur la carte. Utilisez-le là où une erreur est peu coûteuse à détecter : code standard, refactorisations, documentation, explications d’erreurs, traduction d’une spécification en code, squelettes de tests. Méfiez-vous-en précisément là où une erreur est un chiffre faux qu’un coup d’œil ne détectera pas : les affirmations CDISC et de terminologie contrôlée, le choix de la méthode statistique et les erreurs de logique silencieuses comme la jointure interne par défaut ci-dessus. Puis tenez la seule ligne qui rend tout cela défendable — le code rédigé par l’IA est non qualifié tant qu’un humain qualifié ne l’a pas relu et qu’il n’a pas franchi les mêmes barrières que tout code. La démo l’a dit clairement : le code s’est exécuté, le tableau avait l’air correct, et une barrière indépendante a prouvé qu’il était faux. L’IA change la vitesse du premier brouillon. Elle ne change rien à qui est responsable du résultat. The runtime is the judge.
Cette leçon est reproductible : le bug de jointure interne rédigé par l’IA qui corrompt les décomptes de la population de sécurité, la barrière diffdf() qui l’attrape, et la jointure gauche corrigée qui passe 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 produit dans votre propre outillage ; le R qui valide le brouillon est réel et s’exécute. The runtime is the judge.
Leçons connexes
- Une SOP d’IA auditable pour la programmation clinique — la procédure de gouvernance qui rend cette carte opérationnelle : la piste d’audit prompt → brouillon → revue → approuvé qui rend le code assisté par IA défendable. · Double programmation en R avec diffdf — la barrière de vérification indépendante qui a attrapé la perte de lignes silencieuse ci-dessus. · Qualification de package avec riskmetric — le prisme fondé sur le risque que visent les cadres, appliqué aux packages R dont dépend un brouillon d’IA. · Créer ADSL en R avec admiral — le type de dérivation qu’un assistant pourrait rédiger et que cette carte vous dit de qualifier.
- Où cela s’inscrit : ceci ouvre la série de programmation clinique agentique — la carte honnête des capacités et le principe « valider avant d’utiliser ». Elle repose sur les barrières de QC construites plus tôt (double programmation, assertions, reproductibilité) et les pointe vers le code rédigé par IA ; les leçons suivantes mettent un copilote IA au travail sur de vraies tâches
admiralet de reporting au sein de cette discipline.
Réutilisation
Citation
@online{2026,
author = {},
title = {L’IA pour la programmation clinique en R : ce qui marche, ce
qui échoue},
date = {2026-07-02},
url = {https://www.datanovia.com/learn/pharma-clinical/08-agentic-clinical-programming/ai-capabilities-limits-clinical-programming},
langid = {fr}
}