As a clinical trial statistician or programmer, answer three short questions in Your review: the task, the inputs and outputs, and the AI-assisted review. Agreeing with all three approves this benchmark; disagreeing with any needs a comment. Propose a fix with the Edit button on any source file, or add it to your comments.
We suggest spending no more than 5 minutes on a review. The other tabs beside Your review are background for assessment, not under review.
Summary
README.mdPublic entries: Python and R. Passing coverage requires an installed inventory.
Goal: give each electrocardiogram (ECG) time-point record of a QT study
the plasma concentration of the parent drug measured at the same nominal
time, for the concentration-QT analysis: flag the records with a matching
pharmacokinetic (PK) sample (ECGPCFL), carry the concentration
(PKCONC), and flag the records the concentration-QT analysis uses
(CQTANLFL).
Input: the ECG time-point averages with their actual treatment
(TRTA), time-matched baseline and change from baseline, one record per
subject, parameter, analysis period (APERIOD), nominal day within the
period (APERDAY) and nominal time point (ATPT, hours after the dose
time in ATPTN); and the plasma concentrations, one record per subject,
period, period day, time point and analyte (the parent drug DRGX and a
metabolite), with AVAL empty and LLOQFL Y for a result below the
lower limit of quantification.
Variables:
TRTA,AVALU,ABLFL,BASE,CHG,BASETYPE: as in the ECG input.ECGPCFL:Ywhen the concentrations hold a parent-drug sample of the same subject, period, period day and nominal time point, whatever its result; no value otherwise. A sample at another time point, even the nearest one, and a metabolite result never match.PKCONC: that sample's parent-drug concentration in ng/mL, as recorded and not rounded, on records of any treatment. Nothing is imputed: no value for a result below the limit or when no sample matches, except on placebo records (TRTA"Placebo"), which hold 0 whenever no quantified result exists, the baseline day included.CQTANLFL:Ywhen the record has both a change from baseline and a concentration; no value otherwise.
Note: a PK sample without an ECG record at its time point adds no record, and whether a record is placebo follows its own period's treatment.
Inputs
Under review2 source filesinput/adeg_raw.csv
Edit16 rows| STUDYID | USUBJID | TRTA | PARAMCD | PARAM | APERIOD | APERDAY | ATPT | ATPTN | AVAL | AVALU | ABLFL | BASE | CHG | BASETYPE |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TQT-01 | Placebo | QTCF | QTcF Interval | 1 | -1 | 2 h | 2 | 402.333 | msec | Y | 402.333 | — | Period 1 Baseline Day 2 h | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 1 | 1 | 2 h | 2 | 404 | msec | — | 402.333 | 1.6669999999999732 | Period 1 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | -1 | 2 h | 2 | 399.667 | msec | Y | 399.667 | — | Period 2 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 411.333 | msec | — | 399.667 | 11.666000000000054 | Period 2 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | -1 | 2 h | 2 | 395 | msec | Y | 395 | — | Period 1 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | -1 | 12 h | 12 | 391.667 | msec | Y | 391.667 | — | Period 1 Baseline Day 12 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | 1 | 2 h | 2 | 408.667 | msec | — | 395 | 13.666999999999973 | Period 1 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | 1 | 12 h | 12 | 397.333 | msec | — | 391.667 | 5.666000000000054 | Period 1 Baseline Day 12 h | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | -1 | 2 h | 2 | 396.333 | msec | Y | 396.333 | — | Period 2 Baseline Day 2 h | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 398 | msec | — | 396.333 | 1.6669999999999732 | Period 2 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | -1 | 0 h | 0 | 410.333 | msec | Y | 410.333 | — | Period 1 Baseline Day 0 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | 1 | 0 h | 0 | 411.667 | msec | — | 410.333 | 1.3339999999999463 | Period 1 Baseline Day 0 h | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | -1 | 2 h | 2 | 407 | msec | Y | 407 | — | Period 2 Baseline Day 2 h | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 409.333 | msec | — | 407 | 2.333000000000027 | Period 2 Baseline Day 2 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | -1 | 0 h | 0 | 412.333 | msec | Y | 412.333 | — | Period 2 Baseline Day 0 h | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 415.667 | msec | — | — | — | Period 2 Baseline Day 2 h |
input/adpc.csv
Edit10 rows| STUDYID | USUBJID | TRTA | APERIOD | APERDAY | ATPT | ATPTN | PARAMCD | PARAM | AVAL | AVALU | LLOQFL |
|---|---|---|---|---|---|---|---|---|---|---|---|
| TQT-01 | Placebo | 1 | 1 | 2 h | 2 | DRGX | Drug X | — | ng/mL | Y | |
| TQT-01 | Drug X | 2 | 1 | 2 h | 2 | MET1 | Drug X Metabolite M1 | 36.2 | ng/mL | — | |
| TQT-01 | Drug X | 2 | 1 | 2 h | 2 | DRGX | Drug X | 148 | ng/mL | — | |
| TQT-01 | Drug X | 1 | 1 | 2 h | 2 | DRGX | Drug X | 171 | ng/mL | — | |
| TQT-01 | Drug X | 1 | 1 | 2 h | 2 | MET1 | Drug X Metabolite M1 | 41.5 | ng/mL | — | |
| TQT-01 | Drug X | 1 | 1 | 14 h | 14 | DRGX | Drug X | 62.4 | ng/mL | — | |
| TQT-01 | Drug X | 1 | 1 | 14 h | 14 | MET1 | Drug X Metabolite M1 | 22.8 | ng/mL | — | |
| TQT-01 | Drug X | 1 | 1 | 0 h | 0 | DRGX | Drug X | — | ng/mL | Y | |
| TQT-01 | Placebo | 2 | 1 | 2 h | 2 | DRGX | Drug X | 1.2 | ng/mL | — | |
| TQT-01 | Drug X | 2 | 1 | 2 h | 2 | DRGX | Drug X | 139 | ng/mL | — |
Expected output
Under review16 expected rowsexpected/adeg.csv
Edit16 rows| STUDYID | USUBJID | TRTA | PARAMCD | PARAM | APERIOD | APERDAY | ATPT | ATPTN | AVAL | AVALU | ABLFL | BASE | CHG | BASETYPE | ECGPCFL | PKCONC | CQTANLFL |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TQT-01 | Placebo | QTCF | QTcF Interval | 1 | -1 | 2 h | 2 | 402.333 | msec | Y | 402.333 | — | Period 1 Baseline Day 2 h | — | 0 | — | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 1 | 1 | 2 h | 2 | 404 | msec | — | 402.333 | 1.6669999999999732 | Period 1 Baseline Day 2 h | Y | 0 | Y | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | -1 | 2 h | 2 | 399.667 | msec | Y | 399.667 | — | Period 2 Baseline Day 2 h | — | — | — | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 411.333 | msec | — | 399.667 | 11.666000000000054 | Period 2 Baseline Day 2 h | Y | 148 | Y | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | -1 | 2 h | 2 | 395 | msec | Y | 395 | — | Period 1 Baseline Day 2 h | — | — | — | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | -1 | 12 h | 12 | 391.667 | msec | Y | 391.667 | — | Period 1 Baseline Day 12 h | — | — | — | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | 1 | 2 h | 2 | 408.667 | msec | — | 395 | 13.666999999999973 | Period 1 Baseline Day 2 h | Y | 171 | Y | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | 1 | 12 h | 12 | 397.333 | msec | — | 391.667 | 5.666000000000054 | Period 1 Baseline Day 12 h | — | — | — | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | -1 | 2 h | 2 | 396.333 | msec | Y | 396.333 | — | Period 2 Baseline Day 2 h | — | 0 | — | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 398 | msec | — | 396.333 | 1.6669999999999732 | Period 2 Baseline Day 2 h | — | 0 | Y | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | -1 | 0 h | 0 | 410.333 | msec | Y | 410.333 | — | Period 1 Baseline Day 0 h | — | — | — | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 1 | 1 | 0 h | 0 | 411.667 | msec | — | 410.333 | 1.3339999999999463 | Period 1 Baseline Day 0 h | Y | — | — | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | -1 | 2 h | 2 | 407 | msec | Y | 407 | — | Period 2 Baseline Day 2 h | — | 0 | — | |
| TQT-01 | Placebo | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 409.333 | msec | — | 407 | 2.333000000000027 | Period 2 Baseline Day 2 h | Y | 1.2 | Y | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | -1 | 0 h | 0 | 412.333 | msec | Y | 412.333 | — | Period 2 Baseline Day 0 h | — | — | — | |
| TQT-01 | Drug X | QTCF | QTcF Interval | 2 | 1 | 2 h | 2 | 415.667 | msec | — | — | — | Period 2 Baseline Day 2 h | Y | 139 | — |
Human review and assessment
| Dataset Name | Variable Name | Variable Label | Type | Codelist/Controlled Terms | Core | Computational Method | Origin |
|---|---|---|---|---|---|---|---|
| ADEG | STUDYID | Study Identifier | character | Copy value from ADEG_RAW.STUDYID. | Predecessor | ||
| ADEG | USUBJID | Unique Subject Identifier | character | Copy value from ADEG_RAW.USUBJID. | Predecessor | ||
| ADEG | TRTA | Actual Treatment | character | Copy value from ADEG_RAW.TRTA. | Predecessor | ||
| ADEG | PARAMCD | Parameter Code | character | Copy value from ADEG_RAW.PARAMCD. | Predecessor | ||
| ADEG | PARAM | Parameter | character | Copy value from ADEG_RAW.PARAM. | Predecessor | ||
| ADEG | APERIOD | Period | numeric | Copy value from ADEG_RAW.APERIOD. | Predecessor | ||
| ADEG | APERDAY | Analysis Nominal Period Day | numeric | Copy value from ADEG_RAW.APERDAY. | Predecessor | ||
| ADEG | ATPT | Analysis Time Point | character | Copy value from ADEG_RAW.ATPT. | Predecessor | ||
| ADEG | ATPTN | Analysis Time Point (N) | numeric | Copy value from ADEG_RAW.ATPTN. | Predecessor | ||
| ADEG | AVAL | Analysis Value | numeric | Copy value from ADEG_RAW.AVAL. | Predecessor | ||
| ADEG | AVALU | Analysis Value Unit | character | Copy value from ADEG_RAW.AVALU. | Predecessor | ||
| ADEG | ABLFL | Baseline Record Flag | character | Copy value from ADEG_RAW.ABLFL. | Predecessor | ||
| ADEG | BASE | Baseline Value | numeric | Copy value from ADEG_RAW.BASE. | Predecessor | ||
| ADEG | CHG | Change from Baseline | numeric | Copy value from ADEG_RAW.CHG. | Predecessor | ||
| ADEG | BASETYPE | Baseline Type | character | Copy value from ADEG_RAW.BASETYPE. | Predecessor | ||
| ADEG | ECGPCFL | ECG Matching PK Flag | character | Y | "Y" when SAMPLED = 1, with SAMPLED taken from the ADPC record matching on STUDYID, USUBJID, APERIOD, APERDAY and ATPTN, where ADPC.PARAMCD = 'DRGX', where SAMPLED is derived as set constant value "1", and no match yields "0"; blank otherwise. | Derived | |
| ADEG | PKCONC | Time-Matched Plasma Concentration | numeric | If SAMPLED = 1 AND AVAL IS NOT NULL, with SAMPLED taken from the ADPC record matching on STUDYID, USUBJID, APERIOD, APERDAY and ATPTN, where ADPC.PARAMCD = 'DRGX', where SAMPLED is derived as set constant value "1", and no match yields "0" and AVAL taken from the ADPC record matching on STUDYID, USUBJID, APERIOD, APERDAY and ATPTN, where ADPC.PARAMCD = 'DRGX', and no match yields "0" then "PARENT_PK.AVAL"; If TRTA = 'Placebo' then "0.0"; otherwise blank. | Derived | ||
| ADEG | CQTANLFL | Concentration QT Analysis Flag | character | Y | "Y" when CHG IS NOT NULL AND PKCONC IS NOT NULL; blank otherwise. | Derived |
| Variable | Permitted values |
|---|---|
| ECGPCFL | Y |
| CQTANLFL | Y |
| Version | Date | Author | Description | Reviewer | Sign-off |
|---|---|---|---|---|---|
| 1.7 | 2026-10-20 | yamaa docs build | Read a specification in the 1.0 surface as its 0.5 counterpart; state that missing values stay missing where a mapping declares no missing handler, and leave out a declared missing answer that restates a handler's default | ||
| 1.6 | 2026-10-17 | yamaa docs build | Describe collected date parts written as ISO 8601 date text and times of day counted in seconds since midnight | ||
| 1.5 | 2026-10-17 | yamaa docs build | Name collected precision in words instead of letter codes; state imputation fallbacks, minimum source precision, bounds ignored outside the collected period, and invalid text with no handler as an error; describe date and datetime shifts, imputation flag codes, and partial text giving no date part | ||
| 1.4 | 2026-10-15 | yamaa docs build | State datetime precision codes through the hour and minute, and complete only the time parts a collected datetime lacks | ||
| 1.3 | 2026-09-29 | yamaa docs build | Show study codelist names, external dictionaries, and ISO 8601 formats in variable rows; list the document's codelist values and metadata | ||
| 1.2 | 2026-09-29 | yamaa docs build | Classify ADaM copies from a declared input as Predecessor and recodes as Derived, and SDTM recodes of locally derived columns as Derived | ||
| 1.1 | 2026-09-29 | yamaa docs build | Resolve lookups into the donor record they select, and give every derivation shape a plain-language rule instead of its raw YAML | ||
| 1.0 | yamaa docs build | Initial generation from spec.yaml |
prompts/adam-adeg-time-matched-concentration/full.md
Edit28 linesFollowing CDISC ADaM standards, use the provided ADEG_RAW and ADPC datasets to create an ADEG dataset with one record per subject, parameter, analysis period, nominal day within the period, and nominal time point.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ECGPCFL, PKCONC, CQTANLFL
ECGPCFL is Y when the concentrations hold a sample of the parent drug DRGX for the same subject, period, period day, and nominal time point; it has no value otherwise. A sample whose result is below the lower limit of quantification still matches. A sample at another time point, even the nearest one, never matches, and neither does a metabolite result.
PKCONC is the matching sample's concentration in ng/mL, as recorded and not rounded, on records of any treatment. PKCONC has no value when the matching sample's result is below the lower limit of quantification or when no sample matches. On placebo records, where TRTA is "Placebo", PKCONC is 0 whenever no quantified result exists, on the baseline day as on any other day. Whether a record is a placebo record follows its own period's treatment.
CQTANLFL is Y when the record has both a change from baseline and a concentration; it has no value otherwise. A PK sample with no ECG record at its time point adds no record.
Read the source datasets from /app/input and save the completed dataset as /app/output/adeg.csv.
prompts/adam-adeg-time-matched-concentration/conventions.md
Edit13 linesFollowing CDISC ADaM standards, use the provided ADEG_RAW and ADPC datasets to create an ADEG dataset with one record per subject, parameter, analysis period, nominal day within the period, and nominal time point.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ECGPCFL, PKCONC, CQTANLFL
ECGPCFL is Y or has no value. PKCONC is as recorded and not rounded. CQTANLFL is Y or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/adeg.csv.
prompts/adam-adeg-time-matched-concentration/brief.md
Edit10 linesFollowing CDISC ADaM standards, use the provided ADEG_RAW and ADPC datasets to create an ADEG dataset with one record per subject, parameter, analysis period, nominal day within the period, and nominal time point.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ECGPCFL, PKCONC, CQTANLFL
Read the source datasets from /app/input and save the completed dataset as /app/output/adeg.csv.
R
Edit3 lineslibrary(yamaa)yamaa_spec("spec.yaml")$run()$outputPython
Edit3 linesimport yamaayamaa.spec("spec.yaml").run().outputsolutions/adam-adeg-time-matched-concentration/result.R
Edit55 lines# Reference solution for the yamaa benchmark adam-adeg-time-matched-concentration (R track).## Written from the benchmark's full prompt and its inputs alone, as an agent# would write it. Harbor's oracle agent runs it to check that the prompt can# be solved and that the grader scores a correct answer 1.library(dplyr, warn.conflicts = FALSE)library(readr)numbers <- cols( APERIOD = col_integer(), APERDAY = col_integer(), ATPTN = col_double(), AVAL = col_double(), BASE = col_double(), CHG = col_double(), .default = col_character())adeg <- read_csv("/app/input/adeg_raw.csv", col_types = numbers, na = "")adpc <- read_csv( "/app/input/adpc.csv", col_types = cols( APERIOD = col_integer(), APERDAY = col_integer(), ATPTN = col_double(), AVAL = col_double(), .default = col_character() ), na = "")# The parent drug's sample at exactly the same subject, period, period day# and nominal time point; metabolite records are never used.parent <- adpc |> filter(PARAMCD == "DRGX") |> transmute(STUDYID, USUBJID, APERIOD, APERDAY, ATPTN, SAMPLED = TRUE, PKAVAL = AVAL)adeg_out <- adeg |> left_join( parent, by = c("STUDYID", "USUBJID", "APERIOD", "APERDAY", "ATPTN"), relationship = "many-to-one" ) |> mutate( # A sample whatever its result, also below the limit. ECGPCFL = if_else(!is.na(SAMPLED), "Y", NA_character_), # As recorded; nothing imputed, except 0 for placebo without a # quantified result. PKCONC = case_when( !is.na(PKAVAL) ~ PKAVAL, TRTA == "Placebo" ~ 0, .default = NA_real_ ), CQTANLFL = if_else(!is.na(CHG) & !is.na(PKCONC), "Y", NA_character_) ) |> select(all_of(c(names(adeg), "ECGPCFL", "PKCONC", "CQTANLFL")))dir.create("/app/output", showWarnings = FALSE)write_csv(adeg_out, "/app/output/adeg.csv", na = "")solutions/adam-adeg-time-matched-concentration/result.py
Edit120 lines# Reference solution for the yamaa benchmark adam-adeg-time-matched-concentration (Python track).## Written from the benchmark's full prompt and its inputs alone, as an agent# would write it. Harbor's oracle agent runs it to check that the prompt can# be solved and that the grader scores a correct answer 1."""Build ADEG from ADEG_RAW and ADPC.Adds time-matched pharmacokinetic concentrations from the parent drugDRGX onto each ECG record. A DRGX sample matches an ECG record only atthe same subject, analysis period, period day, and nominal time point.Values are carried through exactly as recorded."""import csvINPUT_DIR = "/app/input"OUTPUT_DIR = "/app/output"def read_rows(path): with open(path, newline="") as handle: return list(csv.DictReader(handle))adeg_rows = read_rows(f"{INPUT_DIR}/adeg_raw.csv")adpc_rows = read_rows(f"{INPUT_DIR}/adpc.csv")# Index the parent-drug samples by subject, period, period day, and# nominal time point. Metabolite results never match.pk_samples = {}for sample in adpc_rows: if sample["PARAMCD"] != "DRGX": continue key = ( sample["USUBJID"], sample["APERIOD"], sample["APERDAY"], sample["ATPTN"], ) pk_samples[key] = sampleoutput_rows = []for record in adeg_rows: key = ( record["USUBJID"], record["APERIOD"], record["APERDAY"], record["ATPTN"], ) sample = pk_samples.get(key) if sample is None: flag = "" concentration = "" else: # A matched sample sets the flag even when its result is below # the lower limit of quantification, but such a result gives # no concentration. flag = "Y" if sample["LLOQFL"] == "Y" or sample["AVAL"] == "": concentration = "" else: concentration = sample["AVAL"] # On placebo records a missing concentration is zero, on the # baseline day as on any other day. The record's own treatment # decides whether it is a placebo record. if concentration == "" and record["TRTA"] == "Placebo": concentration = "0" # The concentration-QTc analysis flag needs both a change from # baseline and a concentration. analysis_flag = ( "Y" if record["CHG"] != "" and concentration != "" else "" ) output_rows.append( { "STUDYID": record["STUDYID"], "USUBJID": record["USUBJID"], "TRTA": record["TRTA"], "PARAMCD": record["PARAMCD"], "PARAM": record["PARAM"], "APERIOD": record["APERIOD"], "APERDAY": record["APERDAY"], "ATPT": record["ATPT"], "ATPTN": record["ATPTN"], "AVAL": record["AVAL"], "AVALU": record["AVALU"], "ABLFL": record["ABLFL"], "BASE": record["BASE"], "CHG": record["CHG"], "BASETYPE": record["BASETYPE"], "ECGPCFL": flag, "PKCONC": concentration, "CQTANLFL": analysis_flag, } )columns = [ "STUDYID", "USUBJID", "TRTA", "PARAMCD", "PARAM", "APERIOD", "APERDAY", "ATPT", "ATPTN", "AVAL", "AVALU", "ABLFL", "BASE", "CHG", "BASETYPE", "ECGPCFL", "PKCONC", "CQTANLFL",]with open(f"{OUTPUT_DIR}/adeg.csv", "w", newline="") as handle: writer = csv.DictWriter(handle, fieldnames=columns) writer.writeheader() writer.writerows(output_rows)solutions/adam-adeg-time-matched-concentration/result.sas
Edit60 lines/* opensas reference solution for the yamaa benchmark adam-adeg-time-matched-concentration. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data adeg; length STUDYID USUBJID TRTA PARAMCD PARAM ATPT AVALU ABLFL BASETYPE $1024; infile "/app/input/adeg_raw.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. TRTA : $char1024. PARAMCD : $char1024. PARAM : $char1024. APERIOD APERDAY ATPT : $char1024. ATPTN AVAL AVALU : $char1024. ABLFL : $char1024. BASE CHG BASETYPE : $char1024.; RECNO = _n_;run;data adpc; length STUDYID USUBJID TRTA ATPT PARAMCD PARAM AVALU LLOQFL $1024; infile "/app/input/adpc.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. TRTA : $char1024. APERIOD APERDAY ATPT : $char1024. ATPTN PARAMCD : $char1024. PARAM : $char1024. AVAL AVALU : $char1024. LLOQFL : $char1024.;run;/* The parent drug's samples only; metabolite records are never used. */data parent; length P_STUDYID P_USUBJID $1024; set adpc; if PARAMCD = 'DRGX'; P_STUDYID = STUDYID; P_USUBJID = USUBJID; P_APERIOD = APERIOD; P_APERDAY = APERDAY; P_ATPTN = ATPTN; PKAVAL = AVAL; SAMPLED = 1; keep P_STUDYID P_USUBJID P_APERIOD P_APERDAY P_ATPTN PKAVAL SAMPLED;run;/* Exact match on subject, period, period day and nominal time point. */proc sql; create table matched as select a.*, p.PKAVAL, p.SAMPLED from adeg as a left join parent as p on a.STUDYID = p.P_STUDYID and a.USUBJID = p.P_USUBJID and a.APERIOD = p.P_APERIOD and a.APERDAY = p.P_APERDAY and a.ATPTN = p.P_ATPTN order by RECNO;quit;/* As recorded; nothing imputed, except 0 for placebo without a quantified result. */data final; length ECGPCFL CQTANLFL $1; set matched; if SAMPLED = 1 then ECGPCFL = 'Y'; else ECGPCFL = ''; if not missing(PKAVAL) then PKCONC = PKAVAL; else if TRTA = 'Placebo' then PKCONC = 0; else PKCONC = .; if not missing(CHG) and not missing(PKCONC) then CQTANLFL = 'Y'; else CQTANLFL = '';run;proc sql; create table out as select STUDYID, USUBJID, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ECGPCFL, PKCONC, CQTANLFL from final;quit;proc export data=out outfile="/app/output/adeg.csv" dbms=csv replace; run;
yamaa