
Domaine SDTM EX en R avec sdtm.oak : exposition
Mappez un extrait brut de dosage du médicament à l’étude vers un domaine SDTM EX conforme à CDISC en R avec sdtm.oak — la classe d’observation Interventions, les qualificateurs dose/voie/fréquence, les dates ISO 8601, le numéro de séquence et les jours d’étude
Un tutoriel complet et exécutable pour le domaine SDTM EX (exposure, exposition) en R. Découvrez ce qu’est la classe d’observation Interventions de SDTM CDISC (un enregistrement par épisode d’administration, indexé par la variable topic EXTRT), en quoi elle diffère des classes Findings et Events, puis mappez un extrait de dosage brut vers un domaine EX conforme avec sdtm.oak : generate_oak_id_vars() pour la traçabilité des enregistrements, assign_no_ct() pour le traitement et la quantité de dose, assign_ct() pour les qualificateurs de Controlled Terminology (EXDOSU/EXDOSFRM/EXDOSFRQ/EXROUTE), assign_datetime() pour les EXSTDTC/EXENDTC ISO 8601, derive_seq() pour EXSEQ, et derive_study_day() pour EXSTDY/EXENDY — chaque ligne exécutable, l’enregistrement d’exposition que lit chaque analyse d’efficacité et de sécurité.
- EX est un domaine Interventions — une troisième forme d’enregistrement. La classe Findings (signes vitaux, analyses biologiques) enregistre des mesures ; la classe Events (événements indésirables) enregistre des choses qui sont arrivées ; la classe Interventions enregistre des choses administrées au sujet — une ligne par épisode de dosage, indexée par le traitement
EXTRT. - La variable topic est
EXTRT, le traitement administré.assign_no_ct()copie le nom de traitement défini par l’étude tel que collecté ; la quantité de doseEXDOSEest copiée de la même façon. - Les descripteurs de dose, eux, sont contrôlés.
assign_ct()recode l’unité, la forme galénique, la fréquence et la voie collectées vers leurs termes standard CDISC (EXDOSU,EXDOSFRM,EXDOSFRQ,EXROUTE). - Un épisode d’exposition est borné par deux dates ISO 8601.
assign_datetime()construit le début (EXSTDTC) et la fin (EXENDTC) qui fixent la période où le sujet était sous traitement. derive_seq()numérote les épisodes etderive_study_day()les situe sur le calendrier de l’étude.EXSEQest unique par sujet ;EXSTDY/EXENDYcomptent les jours depuis la date de référence — et l’ensemble du domaine devient l’entrée que lisent les variables de traitement d’ADSL.
Introduction
Le sujet a pris 54 mg de médicament à l’étude par voie transdermique de janvier à juin, puis sa dose a été augmentée à 81 mg. Cet enregistrement d’administration a une seule mission : parvenir au régulateur sous la forme du domaine SDTM (Study Data Tabulation Model) EX (exposure, exposition) — l’exposition à laquelle est comparée chaque analyse d’efficacité et de sécurité. Ce que le site enregistre est plus approximatif : une page de CRF (case report form, cahier d’observation) avec un nom de médicament, un nombre, une forme cochée « Patch », une date de début et de fin saisies comme le coordinateur les a saisies. Le travail ici consiste à transformer cet extrait brut en un domaine EX conforme qu’un évaluateur peut ouvrir et lire de la même façon pour n’importe quelle étude.
Cette leçon réalise ce mapping de bout en bout en R avec sdtm.oak, le package pharmaverse pour la transformation des données brutes en SDTM. Elle complète le trio des classes d’observation : le domaine Findings (signes vitaux) enregistre ce qui a été mesuré, le domaine Events (événements indésirables) enregistre ce qui est arrivé, et EX enregistre ce qui a été administré — les mêmes algorithmes oak, une troisième forme d’enregistrement. Le SDTM est l’amont du flux de données clinique — brut → SDTM → ADaM → tables, listings et figures (TLF) — de sorte qu’un domaine EX propre ici permet à la couche d’analyse de dériver les dates de début et de fin de traitement qui ancrent le jeu de données ADSL de niveau sujet.
Voici où nous allons — le domaine EX conforme que nous allons construire, dessiné comme la chronologie d’exposition qu’il encode, directement à partir du résultat mappé :
Chaque segment ici est un enregistrement SDTM — un traitement, une dose, une voie, borné par un début et une fin. À la fin de cette leçon, vous les aurez tous produits à partir d’un extrait brut. Nouveau dans le pipeline plus large ? Commencez par le flux de données des essais cliniques, qui situe où se place le SDTM, et les standards CDISC, qui placent le SDTM aux côtés de CDASH et ADaM.
Ce qu’est la classe Interventions du SDTM
Le SDTM — le Study Data Tabulation Model — est le standard CDISC (Clinical Data Interchange Standards Consortium) pour organiser les données collectées d’un essai en domaines fixes. Il est publié sous la forme du standard fondamental SDTM et du SDTM Implementation Guide (SDTMIG). Le SDTM range chaque observation dans l’une des trois classes générales d’observation, et la classe détermine la forme d’un enregistrement :
| Classe d’observation | Ce qu’elle enregistre | Exemples de domaines | Variable topic |
|---|---|---|---|
| Interventions | Choses administrées au sujet ou pratiquées sur lui | EX (exposition), CM (médicaments concomitants), PR (procédures) | --TRT |
| Events | Choses qui sont arrivées au sujet | AE (événements indésirables), MH (antécédents médicaux), DS (disposition) | --TERM |
| Findings | Mesures et évaluations | VS (signes vitaux), LB (analyses biologiques), EG (ECG) | --TESTCD |
La leçon sur les signes vitaux mappait un domaine Findings, où la variable topic est un code de test (VSTESTCD = « ce qui a été mesuré ») ; la leçon sur les événements indésirables mappait un domaine Events, indexé par un terme rapporté (AETERM = « ce qui est arrivé »). Les Interventions sont la troisième forme. L’exposition au médicament à l’étude n’est ni une mesure ni une occurrence — c’est un traitement administré, donc la variable topic est le traitement EXTRT (« ce qui a été administré »), et il y a un enregistrement par épisode de dosage constant : un nouvel enregistrement à chaque changement de dose, de voie ou de forme — et aussi à un intervalle de dosage protocolaire ou à une limite de visite, de sorte qu’un sujet peut avoir deux enregistrements consécutifs à la même dose. C’est toute la distinction — un traitement au lieu d’un code de test ou d’un terme, un épisode au lieu d’une mesure ou d’un événement.
Un enregistrement EX, c’est ce traitement topic accompagné de ses qualificateurs de dose, identifiants et temporalité :
| Rôle de la variable | Exemple EX | Ce qu’elle porte |
|---|---|---|
| Identifiants | STUDYID, USUBJID, DOMAIN, EXSEQ |
L’étude, le sujet, le code de domaine (EX), et un numéro de séquence unique par enregistrement. |
| Topic | EXTRT |
Le nom du traitement administré (le médicament défini par l’étude ou PLACEBO). |
| Qualificateurs de dose | EXDOSE, EXDOSU, EXDOSFRM, EXDOSFRQ, EXROUTE |
Quantité de dose, unité, forme galénique, fréquence et voie d’administration. |
| Temporalité | EXSTDTC, EXENDTC, EXSTDY, EXENDY |
Début et fin de l’épisode au format ISO 8601 (--DTC), et le jour d’étude de chacun. |
Deux conventions font l’essentiel du mapping. D’abord, la variable topic (EXTRT) nomme l’intervention et tout le reste la qualifie. Ensuite, les descripteurs de dose sont restreints par la Controlled Terminology (CT) — des codelists publiés par CDISC qui fixent les valeurs autorisées (EXROUTE doit valoir TRANSDERMAL, pas « transdermal » ni « patch »). CDISC les maintient sous le nom de SDTM Controlled Terminology. Mapper le brut vers le SDTM consiste, en substance, à remplir les bonnes colonnes de qualificateurs avec les bonnes valeurs valides au regard de la CT — le même travail que pour les Findings et les Events, réalisé pour une troisième forme d’enregistrement.
L’extrait brut de dosage et sa Controlled Terminology
Deux entrées pilotent un mapping : l’extrait brut et la Controlled Terminology de l’étude. sdtm.oak est livré avec des exemples bruts pour les médicaments concomitants et les signes vitaux, mais pas pour l’exposition ; nous construisons donc un petit extrait de dosage brut dans la forme sous laquelle un système EDC (electronic data capture, saisie électronique des données) l’exporte — une ligne large par épisode de dosage, des noms de colonnes choisis par le promoteur, des dates dans le format qu’utilisait le formulaire. Il suit le pilote CDISC public : un médicament à l’étude transdermique titré entre 54 mg et 81 mg face à un bras placebo.
library(sdtm.oak)
library(dplyr, warn.conflicts = FALSE)
# A raw study-drug dosing extract: one row per dosing episode, as collected
ex_raw <- data.frame(
SUBJ = c("1015","1015","1015","1023","1028","1028","1033","1039","1039","1044","1044","1044"),
EXSPID = c("EX01","EX02","EX03","EX01","EX01","EX02","EX01","EX01","EX02","EX01","EX02","EX03"),
DRUG = c("Xanomeline","Xanomeline","Xanomeline","Placebo","Xanomeline","Xanomeline",
"Placebo","Xanomeline","Xanomeline","Xanomeline","Xanomeline","Xanomeline"),
DOSE = c(54, 54, 81, 0, 54, 81, 0, 54, 54, 54, 81, 81),
DOSEU = "mg",
FORM = "Patch",
FREQ = "Once daily",
ROUTE = "Transdermal",
EXSTDAT = c("02 Jan 2014","17 Jan 2014","19 Jun 2014","05 Aug 2012","11 Mar 2013","28 Mar 2013",
"22 Sep 2013","03 Feb 2014","20 Feb 2014","09 Apr 2013","24 Apr 2013","10 Jun 2013"),
EXENDAT = c("16 Jan 2014","18 Jun 2014","02 Jul 2014","27 Aug 2012","27 Mar 2013","30 May 2013",
"18 Oct 2013","19 Feb 2014","30 Jun 2014","23 Apr 2013","09 Jun 2013","25 Jul 2013"),
stringsAsFactors = FALSE
)
ex_raw |>
select(SUBJ, DRUG, DOSE, DOSEU, ROUTE, EXSTDAT, EXENDAT) |>
head() SUBJ DRUG DOSE DOSEU ROUTE EXSTDAT EXENDAT
1 1015 Xanomeline 54 mg Transdermal 02 Jan 2014 16 Jan 2014
2 1015 Xanomeline 54 mg Transdermal 17 Jan 2014 18 Jun 2014
3 1015 Xanomeline 81 mg Transdermal 19 Jun 2014 02 Jul 2014
4 1023 Placebo 0 mg Transdermal 05 Aug 2012 27 Aug 2012
5 1028 Xanomeline 54 mg Transdermal 11 Mar 2013 27 Mar 2013
6 1028 Xanomeline 81 mg Transdermal 28 Mar 2013 30 May 2013
Chaque ligne brute est un épisode de dosage : le traitement (DRUG), la quantité de dose et l’unité (DOSE, DOSEU), la forme galénique, la fréquence et la voie de dose, et la date de début et de fin de l’épisode. Un sujet sous médicament actif a plusieurs lignes consécutives — à mesure que la dose augmente, ou lorsqu’un nouvel intervalle de dosage commence à la même dose. La Controlled Terminology fait correspondre chaque valeur collectée à son terme CDISC standard au sein d’un codelist. Une CT d’étude réelle est livrée dans le cadre de la spécification SDTM ; ici, nous définissons le petit ensemble de codelists de descripteurs de dose dont nous avons besoin :
# Study controlled terminology: collected value -> CDISC standard term, by codelist
ex_ct <- data.frame(
codelist_code = c("C71620", "C66726", "C71113", "C66729"),
term_value = c("mg", "PATCH", "QD", "TRANSDERMAL"), # CDISC standard term
collected_value = c("mg", "Patch", "Once daily", "Transdermal"), # as the CRF recorded it
term_preferred_term = NA_character_, term_synonyms = NA_character_,
stringsAsFactors = FALSE
)
ex_ct |> select(codelist_code, collected_value, term_value) codelist_code collected_value term_value
1 C71620 mg mg
2 C66726 Patch PATCH
3 C71113 Once daily QD
4 C66729 Transdermal TRANSDERMAL
collected_value est ce que le CRF a enregistré ; term_value est le terme standard CDISC que sdtm.oak substituera. Les codelists sont des standards CDISC : C71620 est le codelist Unit (EXDOSU), C66726 le codelist Pharmaceutical Dosage Form (EXDOSFRM), C71113 le codelist Frequency (EXDOSFRQ, où « Once daily » → QD), et C66729 le codelist Route of Administration (EXROUTE). L’argument ct_clst de chaque fonction sensible à la CT pointe vers l’une de ces valeurs codelist_code.
Estampiller la traçabilité des enregistrements avec oak_id_vars
Parce que nous mappons un champ brut à la fois puis recousons les morceaux ensemble, sdtm.oak a besoin d’une clé stable sur chaque ligne brute. generate_oak_id_vars() en ajoute trois : oak_id (le numéro de ligne), raw_source (de quel extrait elle provient) et patient_number.
ex_raw <- ex_raw |>
generate_oak_id_vars(pat_var = "SUBJ", raw_src = "ex_raw")
ex_raw |>
select(oak_id, raw_source, patient_number, DRUG, DOSE) |>
head() oak_id raw_source patient_number DRUG DOSE
1 1 ex_raw 1015 Xanomeline 54
2 2 ex_raw 1015 Xanomeline 54
3 3 ex_raw 1015 Xanomeline 81
4 4 ex_raw 1023 Placebo 0
5 5 ex_raw 1028 Xanomeline 54
6 6 ex_raw 1028 Xanomeline 81
Ces trois colonnes constituent les oak_id_vars. Chaque mapping de qualificateur ci-dessous passe id_vars = oak_id_vars(), ce qui indique à sdtm.oak de joindre la nouvelle colonne sur le bon enregistrement par cette clé — le mécanisme qui permet aux mappings partiels de se combiner sans dupliquer de lignes.
Mapper la variable topic et la quantité de dose
Un enregistrement Interventions commence par son topic — le traitement administré. Contrairement à un code de test Findings, EXTRT est un nom de traitement défini par l’étude copié tel que collecté, nous utilisons donc assign_no_ct() (« assign », parce qu’elle copie une valeur collectée ; « no_ct », parce que nous reprenons le nom de médicament propre à l’étude verbatim). La quantité de dose EXDOSE est de même un nombre collecté, copié de la même façon.
ex <- assign_no_ct(raw_dat = ex_raw, raw_var = "DRUG", tgt_var = "EXTRT") |>
assign_no_ct(raw_dat = ex_raw, raw_var = "DOSE", tgt_var = "EXDOSE",
id_vars = oak_id_vars())
ex |>
select(oak_id, patient_number, EXTRT, EXDOSE) |>
head()# A tibble: 6 × 4
oak_id patient_number EXTRT EXDOSE
<int> <chr> <chr> <dbl>
1 1 1015 Xanomeline 54
2 2 1015 Xanomeline 54
3 3 1015 Xanomeline 81
4 4 1023 Placebo 0
5 5 1028 Xanomeline 54
6 6 1028 Xanomeline 81
Deux colonnes SDTM existent pour l’instant, un enregistrement par épisode brut : le traitement et sa quantité de dose. Les lignes à 0 mg sont le bras placebo — un vrai enregistrement EX, dose comprise, car le SDTM tabule ce qui a été administré, et « placebo, 0 mg » est une administration.
Mapper les qualificateurs de dose de la Controlled Terminology
Maintenant, les colonnes qui décrivent la dose : son unité, sa forme galénique, la fréquence à laquelle elle a été administrée, et par quelle voie. Chacune est une valeur collectée recodée via la Controlled Terminology, chacune utilise donc assign_ct() avec le codelist qui la régit :
EXDOSU(unité de dose) — le codelist UnitC71620:mgrestemg.EXDOSFRM(forme galénique) — le codelist Pharmaceutical Dosage FormC66726:Patch→PATCH.EXDOSFRQ(fréquence) — le codelist FrequencyC71113:Once daily→QD.EXROUTE(voie) — le codelist Route of AdministrationC66729:Transdermal→TRANSDERMAL.
ex <- ex |>
assign_ct(raw_dat = ex_raw, raw_var = "DOSEU", tgt_var = "EXDOSU",
ct_spec = ex_ct, ct_clst = "C71620", id_vars = oak_id_vars()) |>
assign_ct(raw_dat = ex_raw, raw_var = "FORM", tgt_var = "EXDOSFRM",
ct_spec = ex_ct, ct_clst = "C66726", id_vars = oak_id_vars()) |>
assign_ct(raw_dat = ex_raw, raw_var = "FREQ", tgt_var = "EXDOSFRQ",
ct_spec = ex_ct, ct_clst = "C71113", id_vars = oak_id_vars()) |>
assign_ct(raw_dat = ex_raw, raw_var = "ROUTE", tgt_var = "EXROUTE",
ct_spec = ex_ct, ct_clst = "C66729", id_vars = oak_id_vars())
ex |>
select(patient_number, EXTRT, EXDOSE, EXDOSU, EXDOSFRM, EXDOSFRQ, EXROUTE) |>
head()# A tibble: 6 × 7
patient_number EXTRT EXDOSE EXDOSU EXDOSFRM EXDOSFRQ EXROUTE
<chr> <chr> <dbl> <chr> <chr> <chr> <chr>
1 1015 Xanomeline 54 mg PATCH QD TRANSDERMAL
2 1015 Xanomeline 54 mg PATCH QD TRANSDERMAL
3 1015 Xanomeline 81 mg PATCH QD TRANSDERMAL
4 1023 Placebo 0 mg PATCH QD TRANSDERMAL
5 1028 Xanomeline 54 mg PATCH QD TRANSDERMAL
6 1028 Xanomeline 81 mg PATCH QD TRANSDERMAL
Chaque valeur collectée est désormais un terme standard CDISC : la forme est PATCH, la fréquence QD, la voie TRANSDERMAL. C’est tout l’intérêt de la Controlled Terminology — un évaluateur, ou un outil de validation de la FDA, lit les mêmes valeurs codées d’une étude à l’autre, quelle que soit la façon dont chaque site les a formulées sur le CRF.
Lorsqu’un descripteur est le même pour chaque enregistrement, hardcode_ct() est l’outil plus adapté. Ici, chaque épisode est un patch transdermique en une prise par jour, de sorte que EXDOSFRM/EXDOSFRQ/EXROUTE pourraient chacun être hardcodés à leur valeur CT fixe avec hardcode_ct() (comme le fait la leçon sur les signes vitaux pour VSORRESU = "mmHg") au lieu d’être recodés depuis une colonne brute. Nous utilisons assign_ct() parce qu’une étude réelle les collecte enregistrement par enregistrement et peut porter plus d’une forme ou d’une voie — recoder la valeur collectée est le schéma général.
Mapper les variables de temporalité
Un épisode de dosage a un début et une fin, chacun étant une date au format ISO 8601 (variables --DTC). L’ISO 8601 est le standard de date international (2014-01-02) qui rend les dates triables et comparables d’une étude à l’autre. Les dates brutes se trouvent dans deux champs, dans un format non standard ; assign_datetime() les analyse et écrit la colonne conforme.
ex <- ex |>
assign_datetime(raw_dat = ex_raw, raw_var = "EXSTDAT", tgt_var = "EXSTDTC",
raw_fmt = list(c("d-m-y", "dd mmm yyyy")), id_vars = oak_id_vars()) |>
assign_datetime(raw_dat = ex_raw, raw_var = "EXENDAT", tgt_var = "EXENDTC",
raw_fmt = list(c("d-m-y", "dd mmm yyyy")), id_vars = oak_id_vars())
ex |>
select(patient_number, EXTRT, EXDOSE, EXSTDTC, EXENDTC) |>
head()# A tibble: 6 × 5
patient_number EXTRT EXDOSE EXSTDTC EXENDTC
<chr> <chr> <dbl> <iso8601> <iso8601>
1 1015 Xanomeline 54 2014-01-02 2014-01-16
2 1015 Xanomeline 54 2014-01-17 2014-06-18
3 1015 Xanomeline 81 2014-06-19 2014-07-02
4 1023 Placebo 0 2012-08-05 2012-08-27
5 1028 Xanomeline 54 2013-03-11 2013-03-27
6 1028 Xanomeline 81 2013-03-28 2013-05-30
raw_fmt indique à sdtm.oak comment la date brute a été écrite (02 Jan 2014) ; il renvoie la forme standard 2014-01-02. Les dates d’exposition sont généralement collectées au jour près, ce sont donc des valeurs --DTC en date seule — le même assign_datetime() gère aussi un champ d’heure apparié et renvoie sans risque une date partielle lorsqu’un jour brut est inconnu, plutôt que d’en inventer un. La vignette sur la gestion des dates documente l’ensemble complet des formats pris en charge et des règles relatives aux dates partielles.
Ajouter les identifiants, la séquence et les jours d’étude
Un enregistrement conforme a besoin de ses identifiants, d’un numéro de séquence et de sa place sur le calendrier de l’étude. STUDYID, DOMAIN et USUBJID sont de simples affectations ; derive_seq() affecte EXSEQ — un numéro de séquence unique par enregistrement au sein d’un sujet ; et derive_study_day() calcule EXSTDY/EXENDY, le jour d’étude de chaque date par rapport à la date de début de référence du sujet RFSTDTC (portée par le domaine de démographie DM). Le jour d’étude 1 est la date de référence elle-même — il n’y a pas de jour 0.
# The reference start date per subject lives on DM; here is the minimal slice derive_study_day needs
dm <- data.frame(
USUBJID = paste0("CDISCPILOT01-", c("1015","1023","1028","1033","1039","1044")),
RFSTDTC = c("2014-01-02","2012-08-05","2013-03-11","2013-09-22","2014-02-03","2013-04-09"),
stringsAsFactors = FALSE
)
ex <- ex |>
mutate(
STUDYID = "CDISCPILOT01",
DOMAIN = "EX",
USUBJID = paste0(STUDYID, "-", patient_number)
) |>
derive_seq(tgt_var = "EXSEQ", rec_vars = c("USUBJID", "EXTRT", "EXSTDTC")) |>
derive_study_day(dm_domain = dm, tgdt = "EXSTDTC", refdt = "RFSTDTC", study_day_var = "EXSTDY") |>
derive_study_day(dm_domain = dm, tgdt = "EXENDTC", refdt = "RFSTDTC", study_day_var = "EXENDY") |>
select(STUDYID, DOMAIN, USUBJID, EXSEQ, EXTRT, EXDOSE, EXDOSU, EXDOSFRM, EXDOSFRQ,
EXROUTE, EXSTDTC, EXENDTC, EXSTDY, EXENDY)
head(ex)# A tibble: 6 × 14
STUDYID DOMAIN USUBJID EXSEQ EXTRT EXDOSE EXDOSU EXDOSFRM EXDOSFRQ EXROUTE
<chr> <chr> <chr> <int> <chr> <dbl> <chr> <chr> <chr> <chr>
1 CDISCPILOT… EX CDISCP… 1 Xano… 54 mg PATCH QD TRANSD…
2 CDISCPILOT… EX CDISCP… 2 Xano… 54 mg PATCH QD TRANSD…
3 CDISCPILOT… EX CDISCP… 3 Xano… 81 mg PATCH QD TRANSD…
4 CDISCPILOT… EX CDISCP… 1 Plac… 0 mg PATCH QD TRANSD…
5 CDISCPILOT… EX CDISCP… 1 Xano… 54 mg PATCH QD TRANSD…
6 CDISCPILOT… EX CDISCP… 2 Xano… 81 mg PATCH QD TRANSD…
# ℹ 4 more variables: EXSTDTC <date>, EXENDTC <date>, EXSTDY <int>,
# EXENDY <int>
Voilà un domaine EX conforme : d’abord les colonnes d’identifiants SDTM, puis le topic (EXTRT), les qualificateurs de dose, la temporalité et les jours d’étude. derive_seq() ordonne les enregistrements par rec_vars et les numérote 1, 2, 3… au sein de chaque sujet, de sorte que EXSEQ soit unique par USUBJID ; derive_study_day() situe chaque épisode sur le calendrier de l’étude (le premier patch du sujet -1015 commence au EXSTDY 1 et l’augmentation de dose survient des mois plus tard), ce qui est ce que la couche d’analyse utilise pour calculer la durée d’exposition. Un rapide contrôle structurel confirme le contrat SDTM :
required <- c("STUDYID", "DOMAIN", "USUBJID", "EXSEQ", "EXTRT", "EXDOSE")
all(required %in% names(ex)) # required identifiers + topic present?[1] TRUE
length(unique(ex$DOMAIN)) == 1 # one domain code?[1] TRUE
!any(duplicated(ex[c("USUBJID", "EXSEQ")])) # EXSEQ unique within subject?[1] TRUE
Trois TRUE : le domaine est structurellement sain. Cela correspond aussi à la réalité — les colonnes que nous avons construites (EXTRT, EXDOSE, EXDOSU, EXDOSFRM, EXDOSFRQ, EXROUTE, EXSTDTC, EXENDTC, EXSTDY, EXENDY) sont exactement les variables d’exposition que porte le jeu de données de référence ex publié de pharmaversesdtm. En production, le contrôle complet est un outil de conformité (Pinnacle 21, ou le package pharmaverse sdtmchecks, présenté dans la leçon sur les signes vitaux) qui exécute les mêmes règles d’intégrité qu’un régulateur. Avec un domaine EX conforme en main, la couche d’analyse lit les dates de début et de fin de traitement directement à partir de lui pour construire le jeu de données ADSL de niveau sujet.
Demandez à Prova « comment regrouper des épisodes de dosage EX consécutifs en une exposition totale de niveau sujet et dériver les dates de début et de fin de traitement (TRTSDTM/TRTEDTM) pour ADSL ? » — elle répond en s’appuyant sur les leçons de ce pilier, avec du code exécutable que vous pouvez essayer sur les données d’exemple. The runtime is the judge. Demandez à Prova →
Problèmes fréquents
Vous mettez l’exposition au médicament dans un domaine Findings — en cherchant un --TESTCD et un résultat. C’est le piège de la classe : l’exposition n’est pas une mesure, elle n’a donc ni code de test ni valeur de résultat. C’est une Intervention — un traitement administré — sa variable topic est donc EXTRT (le médicament), mappée avec assign_no_ct(), qualifiée par la dose et la voie, non par un couple test-et-résultat. Si vous cherchez un EXTESTCD, vous avez la mauvaise classe d’observation en tête ; mappez le traitement, pas un test.
assign_ct() avertit qu’une valeur « could not be mapped », et la colonne SDTM conserve le texte brut. La valeur collectée n’est pas dans le codelist que vous avez indiqué — un vrai constat, pas un bug. Une cause fréquente est une différence de casse ou d’orthographe : sdtm.oak fait une correspondance exacte de collected_value, de sorte qu’un "transdermal" brut ne correspondra pas à une entrée de codelist enregistrée comme "Transdermal". Vérifiez le codelist avec subset(ex_ct, codelist_code == "<code>") et confirmez que sa colonne collected_value contient la valeur brute exactement telle qu’écrite ; sdtm.oak laisse passer la valeur non mappée inchangée, pour que vous corrigiez la terminologie, pas les données.
EXSEQ n’est pas unique, ou derive_seq() met deux lignes à égalité. Les rec_vars que vous avez donnés n’ordonnent pas de façon unique les enregistrements au sein d’un sujet. Pour l’EX, un sujet a plusieurs épisodes consécutifs, ordonnez donc par le traitement plus la date de début (c("USUBJID", "EXTRT", "EXSTDTC")) ; si deux épisodes pouvaient partager une date de début, ajoutez un autre champ distinctif pour que chaque enregistrement au sein d’un sujet se trie à une position distincte.
Questions fréquentes
Le domaine SDTM EX (exposure, exposition) est le jeu de données CDISC SDTM qui enregistre l’exposition d’un sujet au traitement à l’étude — un enregistrement standardisé par épisode de dosage continu, dans la classe d’observation Interventions. Chaque enregistrement porte le traitement EXTRT, les qualificateurs de dose (EXDOSE, EXDOSU, EXDOSFRM, EXDOSFRQ, EXROUTE), des dates de début/fin ISO 8601 (EXSTDTC, EXENDTC) avec leurs jours d’étude (EXSTDY, EXENDY), et des identifiants (USUBJID, EXSEQ). C’est un domaine obligatoire dans une soumission réglementaire et la source des dates de traitement et des variables d’exposition dans ADSL et les jeux de données d’analyse de l’exposition.
Ce sont les trois classes générales d’observation du SDTM, distinguées par ce que représente un enregistrement. Interventions enregistre quelque chose d’administré au sujet ou pratiqué sur lui (le médicament à l’étude dans EX, les médicaments concomitants dans CM) — variable topic --TRT. Events enregistre quelque chose qui est arrivé (un événement indésirable dans AE, un antécédent médical dans MH) — variable topic --TERM. Findings enregistre une mesure ou une évaluation (un signe vital dans VS, une analyse biologique dans LB) — variable topic --TESTCD, avec un résultat. Les mêmes algorithmes sdtm.oak, trois formes d’enregistrement : pour l’EX, vous mappez un traitement avec des qualificateurs de dose, non un couple test-et-résultat ni un terme rapporté.
La quantité de dose EXDOSE est un nombre collecté, copié tel quel avec assign_no_ct(). Les descripteurs de dose relèvent de la Controlled Terminology, chacun est donc recodé avec assign_ct() pointé vers son codelist : l’unité EXDOSU (codelist Unit C71620), la forme galénique EXDOSFRM (C66726), la fréquence EXDOSFRQ (C71113, par exemple « Once daily » → QD), et la voie EXROUTE (codelist Route of Administration C66729, par exemple « Transdermal » → TRANSDERMAL). Lorsqu’un descripteur est le même pour chaque enregistrement, vous pouvez hardcode_ct() la valeur fixe à la place. Voir SDTM Controlled Terminology pour les codelists publiés.
Les deux sont des domaines Interventions, mais EX enregistre le traitement à l’étude étudié — le médicament spécifié par le protocole avec lequel le sujet est dosé — tandis que CM (médicaments concomitants) enregistre les autres médicaments que le sujet prend en parallèle (thérapie de fond, médicaments de secours). La forme d’enregistrement est la même (une variable topic de traitement plus des qualificateurs de dose et la temporalité), de sorte que le schéma de mapping sdtm.oak de cette leçon se transpose directement à CM : mappez CMTRT avec assign_no_ct(), les qualificateurs de dose avec assign_ct(), et les dates avec assign_datetime().
Utilisez assign_no_ct() pour les valeurs copiées telles quelles (le traitement EXTRT et la quantité de dose EXDOSE) ; assign_ct() pour les valeurs collectées recodées via un codelist (EXDOSU, EXDOSFRM, EXDOSFRQ, EXROUTE) — ou hardcode_ct() lorsque cette valeur est fixe pour chaque enregistrement ; assign_datetime() pour les dates ISO 8601 (EXSTDTC, EXENDTC) ; derive_seq() pour EXSEQ ; et derive_study_day() pour les jours d’étude EXSTDY/EXENDY. generate_oak_id_vars() estampille d’abord la clé de traçabilité sur laquelle chaque mapping se rejoint. La vignette sur les algorithmes en dresse la liste complète.
Testez vos connaissances
Supposons que l’extrait brut ait gagné un bras de secours dosé sous forme de comprimé oral : un champ FORM collecté comme Tablet et ROUTE collecté comme Oral. Esquissez comment vous étendriez le mapping pour que EXDOSFRM et EXROUTE ressortent en termes standard CDISC — qu’est-ce qui change dans la Controlled Terminology, et quelle fonction sdtm.oak reste la même ?
EXDOSFRM et EXROUTE sont déjà mappés avec assign_ct() — la fonction ne change pas. Ce qui doit changer, c’est la CT de l’étude : les codelists doivent contenir une ligne collected_value → term_value pour chaque nouvelle valeur collectée, dans le bon codelist_code.
Ajoutez les nouveaux termes à ex_ct — le codelist Pharmaceutical Dosage Form C66726 et le codelist Route of Administration C66729 régissent déjà ces variables, vous étendez donc ces codelists, non le code :
# add rows to ex_ct: collected -> CDISC standard term
# codelist_code collected_value term_value
# C66726 "Tablet" "TABLET"
# C66729 "Oral" "ORAL"Les appels assign_ct() pour EXDOSFRM et EXROUTE sont inchangés — ils recodent désormais Tablet → TABLET et Oral → ORAL parce que la CT contient les entrées. C’est exactement pourquoi les algorithmes de sdtm.oak sont réutilisables : le code de mapping est fixe, et la CT de l’étude porte chaque valeur autorisée.
A. Parce que l’EX est un domaine Findings et que EXTRT est son code de test B. Parce que l’EX est un domaine Interventions — il enregistre un traitement administré, indexé par le nom du traitement C. Parce que sdtm.oak exige que chaque domaine utilise une variable topic --TRT
B. L’EX appartient à la classe d’observation Interventions, qui enregistre des choses administrées au sujet. Sa variable topic est donc le traitement EXTRT (« ce qui a été administré »), avec un enregistrement par épisode de dosage — contrairement à la classe Findings (signes vitaux, analyses biologiques), dont le topic est un code de test --TESTCD (« ce qui a été mesuré »). A se trompe de classe (l’EX est Interventions, pas Findings), et C est faux — la variable topic dépend de la classe d’observation, pas d’une règle du package.
Conclusion
Mapper le domaine EX est la même boucle champ par champ que pour n’importe quel domaine SDTM, appliquée à la classe Interventions : remplir la bonne colonne SDTM à partir du bon champ brut avec le bon algorithme. La variable topic EXTRT nomme le traitement (copiée verbatim avec assign_no_ct(), aux côtés de la quantité de dose EXDOSE) ; assign_ct() recode l’unité, la forme, la fréquence et la voie via la Controlled Terminology ; assign_datetime() construit le début et la fin ISO 8601 ; derive_seq() numérote les épisodes ; et derive_study_day() les situe sur le calendrier de l’étude. Maîtrisez la boucle Interventions ici et le domaine des médicaments concomitants (CM) est la même boucle avec des champs différents. Avec un SDTM EX conforme en main, l’étape suivante est la couche d’analyse, où les dates de début et de fin de traitement qu’il porte ancrent le jeu de données ADSL de niveau sujet construit avec admiral.
Cette leçon est reproductible : chaque résultat de cette page a été produit par le code montré — copiez n’importe quel bloc et exécutez-le pour les reproduire. The runtime is the judge.
Leçons connexes
- Mapper des données EDC brutes vers un domaine SDTM Findings avec sdtm.oak — la contrepartie « signes vitaux » de la classe Findings, avec une passe de conformité
sdtmchecks. · Mapper les événements indésirables vers le domaine SDTM AE avec sdtm.oak — la contrepartie Events ; ensemble, ces trois leçons complètent le trio des classes d’observation. · Le flux de données des essais cliniques : du CRF au SDTM, ADaM, TLF — où se place le SDTM dans le pipeline que cette leçon alimente. · Créer ADSL en R avec admiral — l’étape suivante, où les dates de traitement EX ancrent le jeu de données d’analyse de niveau sujet. - Où cela s’inscrit : les fondations réglementaires et CDISC → le mapping de l’exposition au médicament à l’étude vers le domaine SDTM EX (vous êtes ici) → la construction d’ADSL avec admiral → les tables d’exposition et de sécurité que livre chaque soumission. Le SDTM EX est la source standardisée que lit chaque résumé d’exposition en aval.
Réutilisation
Citation
@online{2026,
author = {},
title = {Domaine SDTM EX en R avec sdtm.oak : exposition},
date = {2026-07-01},
url = {https://www.datanovia.com/learn/pharma-clinical/02-sdtm-programming/sdtm-ex-exposure-domain},
langid = {fr}
}