Review ask

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

Lifecycle: draftEditUnder review
What this benchmark means
README.md

Public entries: Python and R. Passing coverage requires an installed inventory.

Goal: add the time-matched placebo comparator of a placebo-controlled parallel-group electrocardiogram (ECG) study given in dose cohorts: flag the placebo records (ACOMPFL), name the placebo group each record is compared with (COMPTYPE), carry that group's means (COMP, COMPBASE, COMPCHG), and correct each drug record's change from baseline by the placebo group's mean change (CCOMPCHG, the double delta).

Input: one record per subject, parameter, analysis period (APERIOD), nominal day within the period (APERDAY) and nominal time point (ATPT, with its number of hours after dosing in ATPTN), each holding the average of the replicate ECGs taken at that time (AVAL, unit AVALU), the subject's dose cohort (COHORT) and actual treatment (TRTA), and its time-matched baseline already in place (ABLFL, BASE, CHG, BASETYPE). The day before dosing is the baseline day; every subject is dosed once.

Variables:

  • ACOMPFL: Y on every placebo record after baseline; no value on drug records and on baseline records.
  • COMPTYPE: "Placebo group at " followed by the time point, for example "Placebo group at 2 h", on every record after baseline, drug and placebo alike, also when no placebo record exists at that time; no value on baseline records.
  • COMP: the mean AVAL of the placebo group: every placebo record after baseline of the same parameter at the same nominal time point, from all cohorts together. No value when the group has no record, and on baseline records.
  • COMPBASE: the mean BASE of the same placebo group, over the records that have one; no value when none has one, and on baseline records.
  • COMPCHG: the mean CHG of the same placebo group, over the records that have one, so not always COMP minus COMPBASE; no value when none has one, and on baseline records.
  • CCOMPCHG: CHG minus COMPCHG on drug records after baseline; no value on placebo and baseline records, or when either value is missing.

Note: a placebo record carries its group's means, not its own values, and none of the comparator values is rounded.

Inputs

Under review
1 source file

input/adeg_raw.csv

Edit
21 rows
input/adeg_raw.csv
STUDYIDUSUBJIDCOHORTTRTAPARAMCDPARAMAPERIODAPERDAYATPTATPTNAVALAVALUABLFLBASECHGBASETYPE
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval1-11 h1398.333msecY398.333—Period 1 Baseline Day 1 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval1-12 h2401.000msecY401.000—Period 1 Baseline Day 2 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval1-14 h4396.667msecY396.667—Period 1 Baseline Day 4 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval111 h1404.667msec—398.3336.334Period 1 Baseline Day 1 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval112 h2409.333msec—401.0008.333Period 1 Baseline Day 2 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval114 h4403.000msec—396.6676.333Period 1 Baseline Day 4 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval111 h1412.333msec———Period 1 Baseline Day 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval1-11 h1393.667msecY393.667—Period 1 Baseline Day 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval1-14 h4391.333msecY391.333—Period 1 Baseline Day 4 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval111 h1396.333msec—393.6672.666Period 1 Baseline Day 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval111 h1405.333msec———Period 1 Baseline Day 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval114 h4402.667msec———Period 1 Baseline Day 4 h
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval1-11 h1389.000msecY389.000—Period 1 Baseline Day 1 h
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval1-14 h4387.333msecY387.333—Period 1 Baseline Day 4 h
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval111 h1399.667msec—389.00010.667Period 1 Baseline Day 1 h
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval114 h4396.000msec—387.3338.667Period 1 Baseline Day 4 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval1-11 h1400.667msecY400.667—Period 1 Baseline Day 1 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval1-12 h2403.333msecY403.333—Period 1 Baseline Day 2 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval1-14 h4398.000msecY398.000—Period 1 Baseline Day 4 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval111 h1402.000msec—400.6671.333Period 1 Baseline Day 1 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval114 h4401.333msec—398.0003.333Period 1 Baseline Day 4 h

Expected output

Under review
21 expected rows

expected/adeg.csv

Edit
21 rows
expected/adeg.csv
STUDYIDUSUBJIDCOHORTTRTAPARAMCDPARAMAPERIODAPERDAYATPTATPTNAVALAVALUABLFLBASECHGBASETYPEACOMPFLCOMPCOMPBASECOMPCHGCCOMPCHGCOMPTYPE
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval1-11 h1398.333msecY398.333—Period 1 Baseline Day 1 h——————
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval1-12 h2401msecY401—Period 1 Baseline Day 2 h——————
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval1-14 h4396.667msecY396.667—Period 1 Baseline Day 4 h——————
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval111 h1404.667msec—398.3336.334Period 1 Baseline Day 1 h—401.22200000000004397.1671.99949999999999984.3345Placebo group at 1 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval112 h2409.333msec—4018.333Period 1 Baseline Day 2 h—————Placebo group at 2 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval114 h4403msec—396.6676.333Period 1 Baseline Day 4 h—4023983.3333Placebo group at 4 h
SAD-01Cohort 1Drug 10 mgQTCFQTcF Interval111 h1412.333msec———Period 1 Baseline Day 1 h—401.22200000000004397.1671.9994999999999998—Placebo group at 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval1-11 h1393.667msecY393.667—Period 1 Baseline Day 1 h——————
SAD-01Cohort 1PlaceboQTCFQTcF Interval1-14 h4391.333msecY391.333—Period 1 Baseline Day 4 h——————
SAD-01Cohort 1PlaceboQTCFQTcF Interval111 h1396.333msec—393.6672.666Period 1 Baseline Day 1 hY401.22200000000004397.1671.9994999999999998—Placebo group at 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval111 h1405.333msec———Period 1 Baseline Day 1 hY401.22200000000004397.1671.9994999999999998—Placebo group at 1 h
SAD-01Cohort 1PlaceboQTCFQTcF Interval114 h4402.667msec———Period 1 Baseline Day 4 hY4023983.333—Placebo group at 4 h
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval1-11 h1389msecY389—Period 1 Baseline Day 1 h——————
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval1-14 h4387.333msecY387.333—Period 1 Baseline Day 4 h——————
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval111 h1399.667msec—38910.667Period 1 Baseline Day 1 h—401.22200000000004397.1671.99949999999999988.6675Placebo group at 1 h
SAD-01Cohort 2Drug 30 mgQTCFQTcF Interval114 h4396msec—387.3338.667Period 1 Baseline Day 4 h—4023983.3335.334Placebo group at 4 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval1-11 h1400.667msecY400.667—Period 1 Baseline Day 1 h——————
SAD-01Cohort 2PlaceboQTCFQTcF Interval1-12 h2403.333msecY403.333—Period 1 Baseline Day 2 h——————
SAD-01Cohort 2PlaceboQTCFQTcF Interval1-14 h4398msecY398—Period 1 Baseline Day 4 h——————
SAD-01Cohort 2PlaceboQTCFQTcF Interval111 h1402msec—400.6671.333Period 1 Baseline Day 1 hY401.22200000000004397.1671.9994999999999998—Placebo group at 1 h
SAD-01Cohort 2PlaceboQTCFQTcF Interval114 h4401.333msec—3983.333Period 1 Baseline Day 4 hY4023983.333—Placebo group at 4 h
Shaded columns are derived— = missing value

Human review and assessment

Your review

3 questions and your comments · View benchmark discussions

Mapping spec

Generated from the benchmark YAML; do not edit by hand

Dataset NameVariable NameVariable LabelTypeCodelist/Controlled TermsCoreComputational MethodOrigin
ADEGSTUDYIDStudy IdentifiercharacterCopy value from ADEG_RAW.STUDYID.Predecessor
ADEGUSUBJIDUnique Subject IdentifiercharacterCopy value from ADEG_RAW.USUBJID.Predecessor
ADEGCOHORTCohortcharacterCopy value from ADEG_RAW.COHORT.Predecessor
ADEGTRTAActual TreatmentcharacterCopy value from ADEG_RAW.TRTA.Predecessor
ADEGPARAMCDParameter CodecharacterCopy value from ADEG_RAW.PARAMCD.Predecessor
ADEGPARAMParametercharacterCopy value from ADEG_RAW.PARAM.Predecessor
ADEGAPERIODPeriodnumericCopy value from ADEG_RAW.APERIOD.Predecessor
ADEGAPERDAYAnalysis Nominal Period DaynumericCopy value from ADEG_RAW.APERDAY.Predecessor
ADEGATPTAnalysis Time PointcharacterCopy value from ADEG_RAW.ATPT.Predecessor
ADEGATPTNAnalysis Time Point (N)numericCopy value from ADEG_RAW.ATPTN.Predecessor
ADEGAVALAnalysis ValuenumericCopy value from ADEG_RAW.AVAL.Predecessor
ADEGAVALUAnalysis Value UnitcharacterCopy value from ADEG_RAW.AVALU.Predecessor
ADEGABLFLBaseline Record FlagcharacterCopy value from ADEG_RAW.ABLFL.Predecessor
ADEGBASEBaseline ValuenumericCopy value from ADEG_RAW.BASE.Predecessor
ADEGCHGChange from BaselinenumericCopy value from ADEG_RAW.CHG.Predecessor
ADEGBASETYPEBaseline TypecharacterCopy value from ADEG_RAW.BASETYPE.Predecessor
ADEGACOMPFLComparator Record FlagcharacterYIf TRTA = 'Placebo' AND ABLFL IS NULL then "Y"; otherwise blank.Derived
ADEGCOMPTYPEComparator TypecharacterIf ABLFL IS NULL then fill the template "Placebo group at {ATPT}"; otherwise blank.Derived
ADEGCOMPComparator ValuenumericIf ABLFL IS NULL then aggregate MEAN(AVAL) over records grouped by PARAMCD, ATPTN, matching on the shared output keys, where ACOMPFL = 'Y'; otherwise blank.Derived
ADEGCOMPBASEBaseline Value of the ComparatornumericIf ABLFL IS NULL then aggregate MEAN(BASE) over records grouped by PARAMCD, ATPTN, matching on the shared output keys, where ACOMPFL = 'Y'; otherwise blank.Derived
ADEGCOMPCHGChange from Baseline in the ComparatornumericIf ABLFL IS NULL then aggregate MEAN(CHG) over records grouped by PARAMCD, ATPTN, matching on the shared output keys, where ACOMPFL = 'Y'; otherwise blank.Derived
ADEGCCOMPCHGComparator corrected change from BLnumericIf COMPTYPE IS NOT NULL AND ACOMPFL IS NULL then compute CHG - COMPCHG; otherwise blank.Derived
VariablePermitted values
ACOMPFLY
VersionDateAuthorDescriptionReviewerSign-off
1.72026-10-20yamaa docs buildRead 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.62026-10-17yamaa docs buildDescribe collected date parts written as ISO 8601 date text and times of day counted in seconds since midnight
1.52026-10-17yamaa docs buildName 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.42026-10-15yamaa docs buildState datetime precision codes through the hour and minute, and complete only the time parts a collected datetime lacks
1.32026-09-29yamaa docs buildShow study codelist names, external dictionaries, and ISO 8601 formats in variable rows; list the document's codelist values and metadata
1.22026-09-29yamaa docs buildClassify ADaM copies from a declared input as Predecessor and recodes as Derived, and SDTM recodes of locally derived columns as Derived
1.12026-09-29yamaa docs buildResolve lookups into the donor record they select, and give every derivation shape a plain-language rule instead of its raw YAML
1.0yamaa docs buildInitial generation from spec.yaml

Agent prompt

The request an agent receives with the input files; each tier states no more than the one above

prompts/adam-adeg-placebo-corrected-change/full.md

Edit
39 lines

Following CDISC ADaM standards, use the provided ADEG_RAW dataset to create an ADEG dataset with one record per subject, parameter, analysis period, nominal day and nominal time point.

The output dataset should contain the following columns in this order: STUDYID, USUBJID, COHORT, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ACOMPFL, COMP, COMPBASE, COMPCHG, CCOMPCHG, COMPTYPE

  • A record with TRTA of "Placebo" is a placebo record; every other record is a drug record.
  • A baseline record is a record with ABLFL of "Y", from the baseline day, the day before dosing; every other record is after baseline.
  • ACOMPFL is "Y" on every placebo record after baseline, and has no value on drug records and on baseline records.
  • COMPTYPE is "Placebo group at " followed by the record's ATPT, on every record after baseline, drug and placebo alike, also when no placebo record exists at that parameter and time point; COMPTYPE has no value on baseline records.
  • The placebo group a record is compared with holds every placebo record after baseline with the same PARAMCD and the same ATPTN, from all cohorts together.
  • COMP is the mean AVAL of that group on every record after baseline; COMP has no value when the group holds no record, and on baseline records.
  • COMPBASE is the mean BASE of the same group, over the records that have a BASE; COMPBASE has no value when no record of the group has one, and on baseline records.
  • COMPCHG is the mean CHG of the same group, over the records that have a CHG, so it is not always COMP minus COMPBASE; COMPCHG has no value when no record of the group has one, and on baseline records.
  • CCOMPCHG is CHG minus COMPCHG on drug records after baseline, and has no value on placebo records and on baseline records, or when CHG or COMPCHG has no value.
  • A placebo record carries its group's means, not its own values, and none of the comparator values is rounded.

Read the source datasets from /app/input and save the completed dataset as /app/output/adeg.csv.

prompts/adam-adeg-placebo-corrected-change/conventions.md

Edit
14 lines

Following CDISC ADaM standards, use the provided ADEG_RAW dataset to create an ADEG dataset with one record per subject, parameter, analysis period, nominal day and nominal time point.

The output dataset should contain the following columns in this order: STUDYID, USUBJID, COHORT, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ACOMPFL, COMP, COMPBASE, COMPCHG, CCOMPCHG, COMPTYPE

ACOMPFL is "Y" or has no value. COMPTYPE is "Placebo group at " followed by the record's ATPT, or has no value. None of the comparator values is rounded.

Read the source datasets from /app/input and save the completed dataset as /app/output/adeg.csv.

prompts/adam-adeg-placebo-corrected-change/brief.md

Edit
11 lines

Following CDISC ADaM standards, use the provided ADEG_RAW dataset to create an ADEG dataset with one record per subject, parameter, analysis period, nominal day and nominal time point.

The output dataset should contain the following columns in this order: STUDYID, USUBJID, COHORT, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ACOMPFL, COMP, COMPBASE, COMPCHG, CCOMPCHG, COMPTYPE

Read the source datasets from /app/input and save the completed dataset as /app/output/adeg.csv.

yamaa code

Public calls generated from benchmark.yaml; results must match the expected output

R

Edit
3 lines
library(yamaa)yamaa_spec("spec.yaml")$run()$output

Python

Edit
3 lines
import yamaayamaa.spec("spec.yaml").run().output

Solution without yamaa

Written from the full prompt and the inputs alone; CI checks it reproduces the expected output

solutions/adam-adeg-placebo-corrected-change/result.R

Edit
64 lines
# Reference solution for the yamaa benchmark adam-adeg-placebo-corrected-change (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)adeg <- read_csv(  "/app/input/adeg_raw.csv",  col_types = cols(    APERIOD = col_integer(), APERDAY = col_integer(),    ATPTN = col_double(), AVAL = col_double(),    BASE = col_double(), CHG = col_double(),    .default = col_character()  ),  na = "")adeg <- adeg |>  mutate(    after_baseline = is.na(ABLFL) | ABLFL != "Y",    ACOMPFL = if_else(after_baseline & TRTA == "Placebo", "Y", NA_character_)  )# The placebo group: every comparator record of the same parameter and# nominal time point, all cohorts together. Each mean skips missing values;# a mean over no value has none.mean_or_na <- function(x) if (all(is.na(x))) NA_real_ else mean(x, na.rm = TRUE)placebo <- adeg |>  filter(ACOMPFL %in% "Y") |>  group_by(PARAMCD, ATPTN) |>  summarise(    COMP = mean_or_na(AVAL),    COMPBASE = mean_or_na(BASE),    COMPCHG = mean_or_na(CHG),    .groups = "drop"  )adeg_out <- adeg |>  left_join(placebo, by = c("PARAMCD", "ATPTN"),            relationship = "many-to-one") |>  mutate(    # Baseline records carry no comparator; placebo records carry the    # group's means like every other record after baseline.    COMP = if_else(after_baseline, COMP, NA_real_),    COMPBASE = if_else(after_baseline, COMPBASE, NA_real_),    COMPCHG = if_else(after_baseline, COMPCHG, NA_real_),    # The double delta, on drug records only.    CCOMPCHG = if_else(after_baseline & is.na(ACOMPFL), CHG - COMPCHG,                       NA_real_),    COMPTYPE = if_else(after_baseline, paste0("Placebo group at ", ATPT),                       NA_character_)  ) |>  select(    STUDYID, USUBJID, COHORT, TRTA, PARAMCD, PARAM, APERIOD, APERDAY, ATPT,    ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ACOMPFL, COMP, COMPBASE,    COMPCHG, CCOMPCHG, COMPTYPE  )dir.create("/app/output", showWarnings = FALSE)write_csv(adeg_out, "/app/output/adeg.csv", na = "")

solutions/adam-adeg-placebo-corrected-change/result.py

Edit
110 lines
# Reference solution for the yamaa benchmark adam-adeg-placebo-corrected-change (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."""Create ADEG with placebo-corrected change columns from ADEG_RAW.Reads /app/input/adeg_raw.csv and writes /app/output/adeg.csv."""import csvfrom pathlib import PathINPUT = Path("/app/input/adeg_raw.csv")OUTPUT = Path("/app/output/adeg.csv")COLUMNS = [    "STUDYID", "USUBJID", "COHORT", "TRTA", "PARAMCD", "PARAM", "APERIOD",    "APERDAY", "ATPT", "ATPTN", "AVAL", "AVALU", "ABLFL", "BASE", "CHG",    "BASETYPE", "ACOMPFL", "COMP", "COMPBASE", "COMPCHG", "CCOMPCHG",    "COMPTYPE",]def to_float(text):    """Parse a CSV cell as a float, returning None for a blank cell."""    if text is None or text.strip() == "":        return None    return float(text)def fmt(value):    """Format a computed float without rounding; blank for None."""    if value is None:        return ""    return repr(value)def mean(values):    vals = [v for v in values if v is not None]    if not vals:        return None    return sum(vals) / len(vals)def main():    with INPUT.open(newline="") as fh:        rows = list(csv.DictReader(fh))    def is_placebo(row):        return row["TRTA"] == "Placebo"    def is_baseline(row):        return row["ABLFL"] == "Y"    # Placebo comparison groups: every placebo record after baseline with    # the same PARAMCD and the same ATPTN, from all cohorts together.    groups = {}    for row in rows:        if is_placebo(row) and not is_baseline(row):            key = (row["PARAMCD"], row["ATPTN"])            groups.setdefault(key, []).append(row)    stats = {}    for key, members in groups.items():        stats[key] = (            mean([to_float(r["AVAL"]) for r in members]),            mean([to_float(r["BASE"]) for r in members]),            mean([to_float(r["CHG"]) for r in members]),        )    out_rows = []    for row in rows:        out = {col: row.get(col, "") for col in COLUMNS[:16]}        baseline = is_baseline(row)        placebo = is_placebo(row)        acompfl = ""        comp = compbase = compchg = None        ccompchg = None        comptype = ""        if not baseline:            key = (row["PARAMCD"], row["ATPTN"])            comp, compbase, compchg = stats.get(key, (None, None, None))            comptype = "Placebo group at " + row["ATPT"]            if placebo:                acompfl = "Y"            else:                chg = to_float(row["CHG"])                if chg is not None and compchg is not None:                    ccompchg = chg - compchg        out["ACOMPFL"] = acompfl        out["COMP"] = fmt(comp)        out["COMPBASE"] = fmt(compbase)        out["COMPCHG"] = fmt(compchg)        out["CCOMPCHG"] = fmt(ccompchg)        out["COMPTYPE"] = comptype        out_rows.append(out)    OUTPUT.parent.mkdir(parents=True, exist_ok=True)    with OUTPUT.open("w", newline="") as fh:        writer = csv.DictWriter(fh, fieldnames=COLUMNS)        writer.writeheader()        writer.writerows(out_rows)if __name__ == "__main__":    main()

solutions/adam-adeg-placebo-corrected-change/result.sas

Edit
68 lines
/* opensas reference solution for the yamaa benchmark adam-adeg-placebo-corrected-change.   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 COHORT 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. COHORT : $char1024. TRTA : $char1024. PARAMCD : $char1024. PARAM : $char1024. APERIOD APERDAY ATPT : $char1024. ATPTN AVAL AVALU : $char1024. ABLFL : $char1024. BASE CHG BASETYPE : $char1024.;run;/* The comparator records: placebo records that are not baseline records. */data flagged;  length ACOMPFL $1;  set adeg;  if ABLFL ne 'Y' then AFTER = 1;  else AFTER = 0;  if AFTER = 1 and TRTA = 'Placebo' then ACOMPFL = 'Y';  else ACOMPFL = '';run;/* The placebo group: every comparator record of the same parameter and   nominal time point, all cohorts together; each mean skips missing values. */data comparator;  length G_PARAMCD $1024;  set flagged;  if ACOMPFL = 'Y';  G_PARAMCD = PARAMCD; G_ATPTN = ATPTN;  keep G_PARAMCD G_ATPTN AVAL BASE CHG;run;proc sql;  create table groups as    select G_PARAMCD, G_ATPTN, mean(AVAL) as G_COMP, mean(BASE) as G_COMPBASE,           mean(CHG) as G_COMPCHG    from comparator    group by G_PARAMCD, G_ATPTN;  create table matched as    select a.*, b.G_COMP, b.G_COMPBASE, b.G_COMPCHG    from flagged as a left join groups as b      on a.PARAMCD = b.G_PARAMCD and a.ATPTN = b.G_ATPTN;quit;/* Placebo records carry the group's means like every other record after   baseline; the double delta is on drug records only. */data final;  length COMPTYPE $1024;  set matched;  if AFTER = 1 then do;    COMP = G_COMP; COMPBASE = G_COMPBASE; COMPCHG = G_COMPCHG;    COMPTYPE = 'Placebo group at ' || strip(ATPT);  end;  else do;    COMP = .; COMPBASE = .; COMPCHG = .;    COMPTYPE = '';  end;  if AFTER = 1 and ACOMPFL ne 'Y' and not missing(CHG) and not missing(COMPCHG)    then CCOMPCHG = CHG - COMPCHG;  else CCOMPCHG = .;run;proc sql;  create table out as    select STUDYID, USUBJID, COHORT, TRTA, PARAMCD, PARAM, APERIOD, APERDAY,           ATPT, ATPTN, AVAL, AVALU, ABLFL, BASE, CHG, BASETYPE, ACOMPFL,           COMP, COMPBASE, COMPCHG, CCOMPCHG, COMPTYPE    from final;quit;proc export data=out outfile="/app/output/adeg.csv" dbms=csv replace; run;