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: select each subject's actual treatment (TRT01A), the first and
last exposure dates and times (TRTSDT, TRTSDTM, TRTEDT, TRTEDTM),
the imputation flags (TRTSTMF, TRTETMF), the treatment duration in days
(TRTDURD), and the safety population flag (SAFFL).
Input: one demographics (DM) record per subject carrying the
actual arm (ACTARM), plus exposure (EX) records carrying the
treatment name (EXTRT), sequence number (EXSEQ), start date
(EXSTDTC), and end date (EXENDTC). Records are built from the
demographics records, so an exposure record with no matching
demographics record adds no record.
Variables:
TRT01A: treatment actually received, uppercased: the treatment of the earliest qualifying exposure (a qualifying record namesVITAMIN D3orPLACEBOand carries a start), with ties on the start broken by the lowerEXSEQ; then the actual arm (ACTARM) when no exposure qualifies; then the textNOT TREATEDwhen neither source names a treatment.TRTSDTandTRTSDTM: date and date/time of the earliest qualifying exposure start, compared as dates and times rather than as text; a start collected without a time uses00:00:00, and a start collected without its day is passed over. Both are blank when the subject has no qualifying exposure record with a full start date.TRTSTMF: which part of the first exposure start's time was imputed:Hwhen the start was collected without a time,Mwhen it stops at the hour andSwhen it stops at the minute; blank when the time was collected to the second or there is no start.TRTEDTandTRTEDTM: date and date/time of the latest exposure end amongVITAMIN D3andPLACEBOrecords (a record need not have a start to name an end); an end collected without a time uses23:59:59, and an end collected without its day is passed over. Both are blank when no such record has an end with a full date.TRTETMF: which part of the last exposure end's time was imputed, as forTRTSTMF; blank when the time was collected to the second or there is no end.TRTDURD: number of days fromTRTSDTtoTRTEDT, counting both the first and the last day (inclusive), so a single treatment day gives one; blank when either date is blank.SAFFL:Ywhen the subject has a treatment start date,Notherwise (never blank).
Note: the exposure dates, date/times, and duration are all present or all blank together; the latest end can come from a record whose start was never collected.
Inputs
Under review2 source filesinput/dm.csv
Edit8 rows| STUDYID | USUBJID | ACTARM |
|---|---|---|
| YAMAA-01 | Vitamin D3 | |
| YAMAA-01 | Placebo | |
| YAMAA-01 | Vitamin D3 | |
| YAMAA-01 | Placebo | |
| YAMAA-01 | Vitamin D3 | |
| YAMAA-01 | — | |
| YAMAA-01 | Vitamin D3 | |
| YAMAA-01 | Placebo |
input/ex.csv
Edit13 rows| STUDYID | USUBJID | EXSEQ | EXTRT | EXDOSE | EXSTDTC | EXENDTC |
|---|---|---|---|---|---|---|
| YAMAA-01 | 1 | VITAMIN D3 | 4000 | 2025-01-08 | 2025-01-14T18:00:00 | |
| YAMAA-01 | 2 | VITAMIN D3 | 4000 | 2025-01-15T08:00:00 | 2025-01-28 | |
| YAMAA-01 | 1 | PLACEBO | 0 | 2025-02-08T09:00:00 | 2025-02-14T17:00:00 | |
| YAMAA-01 | 2 | PLACEBO | 0 | 2025-02-15T09:00:00 | 2025-02-28T17:00:00 | |
| YAMAA-01 | 1 | VITAMIN D3 | 4000 | 2025-03-05 | 2025-03-05 | |
| YAMAA-01 | 1 | VITAMIN D3 | 4000 | 2025-04-03T10:00:00 | 2025-04-10 | |
| YAMAA-01 | 2 | PLACEBO | 0 | 2025-04-03T10:00:00 | 2025-04-16T12:00:00 | |
| YAMAA-01 | 1 | RESCUE MED | 200 | 2025-05-01 | 2025-05-07 | |
| YAMAA-01 | 1 | VITAMIN D3 | 4000 | 2025-06-08T09:00:00 | 2025-06-14T16:00:00 | |
| YAMAA-01 | 2 | VITAMIN D3 | 4000 | — | 2025-06-20 | |
| YAMAA-01 | 1 | PLACEBO | 0 | 2025-07-01T10:00:00 | 2025-07-07T10:00:00 | |
| YAMAA-01 | 2 | PLACEBO | 0 | 2025-07-01T10:00:00 | 2025-07-07T10:00:00 | |
| YAMAA-01 | 1 | VITAMIN D3 | 4000 | 2025-03-08T10:00:00 | 2025-03-21T16:00:00 |
Expected output
Under review8 expected rowsexpected/adsl.csv
Edit8 rows| STUDYID | USUBJID | TRT01A | TRTSDT | TRTSDTM | TRTSTMF | TRTEDT | TRTEDTM | TRTETMF | TRTDURD | SAFFL |
|---|---|---|---|---|---|---|---|---|---|---|
| YAMAA-01 | VITAMIN D3 | 2025-01-08 | 2025-01-08T00:00:00 | H | 2025-01-28 | 2025-01-28T23:59:59 | H | 21 | Y | |
| YAMAA-01 | PLACEBO | 2025-02-08 | 2025-02-08T09:00:00 | — | 2025-02-28 | 2025-02-28T17:00:00 | — | 21 | Y | |
| YAMAA-01 | VITAMIN D3 | 2025-03-05 | 2025-03-05T00:00:00 | H | 2025-03-05 | 2025-03-05T23:59:59 | H | 1 | Y | |
| YAMAA-01 | VITAMIN D3 | 2025-04-03 | 2025-04-03T10:00:00 | — | 2025-04-16 | 2025-04-16T12:00:00 | — | 14 | Y | |
| YAMAA-01 | VITAMIN D3 | — | — | — | — | — | — | — | N | |
| YAMAA-01 | NOT TREATED | — | — | — | — | — | — | — | N | |
| YAMAA-01 | VITAMIN D3 | 2025-06-08 | 2025-06-08T09:00:00 | — | 2025-06-20 | 2025-06-20T23:59:59 | H | 13 | Y | |
| YAMAA-01 | PLACEBO | 2025-07-01 | 2025-07-01T10:00:00 | — | 2025-07-07 | 2025-07-07T10:00:00 | — | 7 | Y |
Human review and assessment
| Dataset Name | Variable Name | Variable Label | Type | Codelist/Controlled Terms | Core | Computational Method | Origin |
|---|---|---|---|---|---|---|---|
| ADSL | STUDYID | Study Identifier | character | Copy value from DM.STUDYID. | Predecessor | ||
| ADSL | USUBJID | Unique Subject Identifier | character | Copy value from DM.USUBJID. | Predecessor | ||
| ADSL | TRT01A | Actual Treatment for Period 01 | character | VITAMIN D3, PLACEBO, NOT TREATED | Convert TRT01SRC to upper case. | Derived | |
| ADSL | TRTSDTM | Datetime of First Exposure to Treatment | numeric | ISO 8601 | Aggregate MIN(EXSTDTM) over records matching on the shared output keys, where EX.EXTRT IN ('VITAMIN D3', 'PLACEBO') AND EX.EXSTDTC IS NOT NULL, with EXSTDTM as impute incomplete datetime from EX.EXSTDTC, giving each time part the source lacks its earliest value; a source without a complete date gives blank; invalid text → blank. | Derived | |
| ADSL | TRTSTMF | Time of First Exposure Imputation Flag | character | H, M, S | Time imputation flag for TRTSDTM: "H" when the whole time was imputed, "M" when the minutes and seconds were, "S" when only the seconds were; blank when the time was collected to the second. | Derived | |
| ADSL | TRTEDTM | Datetime of Last Exposure to Treatment | numeric | ISO 8601 | Aggregate MAX(EXENDTM) over records matching on the shared output keys, where EX.EXTRT IN ('VITAMIN D3', 'PLACEBO') AND EX.EXENDTC IS NOT NULL, with EXENDTM as impute incomplete datetime from EX.EXENDTC, giving each time part the source lacks its latest value; a source without a complete date gives blank; invalid text → blank. | Derived | |
| ADSL | TRTETMF | Time of Last Exposure Imputation Flag | character | H, M, S | Time imputation flag for TRTEDTM: "H" when the whole time was imputed, "M" when the minutes and seconds were, "S" when only the seconds were; blank when the time was collected to the second. | Derived | |
| ADSL | TRTSDT | Date of First Exposure to Treatment | numeric | ISO 8601 | Take the date part of TRTSDTM, blank for a year or a year and month alone. | Derived | |
| ADSL | TRTEDT | Date of Last Exposure to Treatment | numeric | ISO 8601 | Take the date part of TRTEDTM, blank for a year or a year and month alone. | Derived | |
| ADSL | TRTDURD | Total Treatment Duration (Days) | numeric | Whole days from TRTSDT to TRTEDT, counting both endpoints. | Derived | ||
| ADSL | SAFFL | Safety Population Flag | character | Y, N | "Y" when TRTSDT IS NOT NULL; "N" otherwise; "N" when the condition is unknown. | Derived |
| Variable | Permitted values |
|---|---|
| TRT01A | VITAMIN D3, PLACEBO, NOT TREATED |
| TRTSTMF | H, M, S |
| TRTETMF | H, M, S |
| SAFFL | Y, N |
| 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-adsl-treatment/full.md
Edit40 linesFollowing CDISC ADaM standards, use the provided DM and EX datasets to create an ADSL dataset with one record per subject.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRT01A, TRTSDT, TRTSDTM, TRTSTMF, TRTEDT, TRTEDTM, TRTETMF, TRTDURD, SAFFL
TRT01A is the treatment actually received, in upper case. TRT01A is the treatment named by the subject's earliest qualifying exposure record, where a qualifying record names "VITAMIN D3" or "PLACEBO" as its treatment and carries a start date/time, and records with the same start are ordered by the lower EXSEQ. When no exposure record qualifies, TRT01A is the subject's actual arm (ACTARM). When neither an exposure record nor the actual arm names a treatment, TRT01A is "NOT TREATED". TRTSDT is the date of the earliest qualifying exposure start, and TRTSDTM is that start as a date and time, with the date and time joined by a T and a start collected without a time given the time 00:00:00. TRTSDT and TRTSDTM have no value when the subject has no qualifying exposure record. TRTSTMF records which part of the first exposure start's time was supplied: "H" when the start was collected without a time, "M" when its time stops at the hour, and "S" when its time stops at the minute. TRTSTMF has no value when that time was collected to the second or when there is no start. TRTEDT is the date of the latest exposure end among the subject's records naming "VITAMIN D3" or "PLACEBO", whether or not that record carries a start, and TRTEDTM is that end as a date and time, with the date and time joined by a T and an end collected without a time given the time 23:59:59. TRTEDT and TRTEDTM have no value when no record naming "VITAMIN D3" or "PLACEBO" has an end. TRTETMF records which part of the last exposure end's time was supplied, as TRTSTMF does for the start, and has no value when that time was collected to the second or when there is no end. TRTDURD is the number of days from TRTSDT to TRTEDT counting both the first and the last day, so a single treatment day gives one, and it has no value when either date has no value. SAFFL is "Y" when the subject has a treatment start date (TRTSDT) and "N" otherwise, and it always has a value. The start and end dates and times and the duration are either all present or all have no value together.
Read the source datasets from /app/input and save the completed dataset as /app/output/adsl.csv.
prompts/adam-adsl-treatment/conventions.md
Edit18 linesFollowing CDISC ADaM standards, use the provided DM and EX datasets to create an ADSL dataset with one record per subject.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRT01A, TRTSDT, TRTSDTM, TRTSTMF, TRTEDT, TRTEDTM, TRTETMF, TRTDURD, SAFFL
TRT01A is "VITAMIN D3", "PLACEBO", the subject's actual arm (ACTARM), or "NOT TREATED", in upper case. TRTSDTM is a date and time with the date and time joined by a T, and a start collected without a time given the time 00:00:00. TRTEDTM is a date and time with the date and time joined by a T, and an end collected without a time given the time 23:59:59. TRTSTMF is "H", "M" or "S", or has no value. TRTETMF is "H", "M" or "S", or has no value. TRTDURD is the number of days from TRTSDT to TRTEDT counting both the first and the last day, so a single treatment day gives one. SAFFL is "Y" or "N".
Read the source datasets from /app/input and save the completed dataset as /app/output/adsl.csv.
prompts/adam-adsl-treatment/brief.md
Edit9 linesFollowing CDISC ADaM standards, use the provided DM and EX datasets to create an ADSL dataset with one record per subject.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRT01A, TRTSDT, TRTSDTM, TRTSTMF, TRTEDT, TRTEDTM, TRTETMF, TRTDURD, SAFFL
Read the source datasets from /app/input and save the completed dataset as /app/output/adsl.csv.
R
Edit3 lineslibrary(yamaa)yamaa_spec("spec.yaml")$run()$outputPython
Edit3 linesimport yamaayamaa.spec("spec.yaml").run().outputsolutions/adam-adsl-treatment/result.R
Edit80 lines# Reference solution for the yamaa benchmark adam-adsl-treatment (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)library(stringr)library(lubridate)dm <- read_csv( "/app/input/dm.csv", col_types = cols(.default = col_character()))ex <- read_csv( "/app/input/ex.csv", col_types = cols(EXSEQ = col_integer(), .default = col_character()))qual <- c("VITAMIN D3", "PLACEBO")parse_start <- function(x) { x[!is.na(x) & x == ""] <- NA_character_ dt <- suppressWarnings(ymd_hms(x, quiet = TRUE, tz = "UTC")) d <- suppressWarnings(ymd(x, quiet = TRUE, tz = "UTC")) coalesce(dt, as.POSIXct(d, tz = "UTC"))}parse_end <- function(x) { base <- parse_start(x) is_date <- !is.na(x) & x != "" & !str_detect(x, "T") base[is_date] <- base[is_date] + 23 * 3600 + 59 * 60 + 59 base}ex_dt <- ex |> mutate( `__start_dt` = parse_start(EXSTDTC), `__end_dt` = parse_end(EXENDTC) )first_start <- ex_dt |> filter(EXTRT %in% qual, !is.na(`__start_dt`)) |> arrange(`__start_dt`, EXSEQ) |> distinct(STUDYID, USUBJID, .keep_all = TRUE) |> select(STUDYID, USUBJID, TRT01RAW = EXTRT, `__stdtm` = `__start_dt`, `__stdtc` = EXSTDTC)last_end <- ex_dt |> filter(EXTRT %in% qual, !is.na(`__end_dt`)) |> arrange(desc(`__end_dt`)) |> distinct(STUDYID, USUBJID, .keep_all = TRUE) |> select(STUDYID, USUBJID, `__endtm` = `__end_dt`, `__endtc` = EXENDTC)adsl <- dm |> left_join(first_start, by = c("STUDYID", "USUBJID")) |> left_join(last_end, by = c("STUDYID", "USUBJID")) |> mutate( `__src` = coalesce(TRT01RAW, ACTARM), TRT01A = case_when( is.na(`__src`) | `__src` == "" ~ "NOT TREATED", .default = str_to_upper(`__src`) ), TRTSDTM = format(`__stdtm`, "%Y-%m-%dT%H:%M:%S", tz = "UTC"), TRTSDT = as.Date(`__stdtm`, tz = "UTC"), TRTSTMF = if_else(!is.na(`__stdtc`) & !str_detect(`__stdtc`, "T"), "H", NA_character_), TRTEDTM = format(`__endtm`, "%Y-%m-%dT%H:%M:%S", tz = "UTC"), TRTEDT = as.Date(`__endtm`, tz = "UTC"), TRTETMF = if_else(!is.na(`__endtc`) & !str_detect(`__endtc`, "T"), "H", NA_character_), TRTDURD = as.integer(TRTEDT - TRTSDT) + 1L, SAFFL = if_else(is.na(TRTSDT), "N", "Y") ) |> select( STUDYID, USUBJID, TRT01A, TRTSDT, TRTSDTM, TRTSTMF, TRTEDT, TRTEDTM, TRTETMF, TRTDURD, SAFFL ) |> arrange(USUBJID)dir.create("/app/output", showWarnings = FALSE)write_csv(adsl, "/app/output/adsl.csv", na = "")solutions/adam-adsl-treatment/result.py
Edit158 lines# Reference solution for the yamaa benchmark adam-adsl-treatment (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 ADSL (one record per subject) from DM and EX.Reads /app/input/dm.csv and /app/input/ex.csv and writes/app/output/adsl.csv with columns:STUDYID, USUBJID, TRT01A, TRTSDT, TRTSDTM, TRTSTMF, TRTEDT, TRTEDTM,TRTETMF, TRTDURD, SAFFL"""import csvfrom datetime import datetime, timeINPUT_DIR = "/app/input"OUTPUT_PATH = "/app/output/adsl.csv"NAMED_TREATMENTS = {"VITAMIN D3", "PLACEBO"}COLUMNS = [ "STUDYID", "USUBJID", "TRT01A", "TRTSDT", "TRTSDTM", "TRTSTMF", "TRTEDT", "TRTEDTM", "TRTETMF", "TRTDURD", "SAFFL",]def parse_dtc(value): """Split an ISO 8601 date/time collection value. Returns (date, time_or_None, has_value). A value without a "T" separator was collected as a date only. """ value = (value or "").strip() if not value: return None, None, False if "T" in value: date_part, time_part = value.split("T", 1) parsed_time = datetime.strptime(time_part.strip(), "%H:%M:%S").time() return ( datetime.strptime(date_part.strip(), "%Y-%m-%d").date(), parsed_time, True, ) return datetime.strptime(value, "%Y-%m-%d").date(), None, Truedef read_rows(path): with open(path, newline="") as handle: return list(csv.DictReader(handle))def main(): dm_rows = read_rows(f"{INPUT_DIR}/dm.csv") ex_rows = read_rows(f"{INPUT_DIR}/ex.csv") ex_by_subject = {} for row in ex_rows: ex_by_subject.setdefault(row["USUBJID"], []).append(row) output_rows = [] for dm in dm_rows: subject_ex = ex_by_subject.get(dm["USUBJID"], []) # Qualifying exposure records: named treatment and a start value. qualifying = [] for row in subject_ex: if row["EXTRT"].strip() not in NAMED_TREATMENTS: continue start_date, start_time, has_start = parse_dtc(row["EXSTDTC"]) if has_start: effective = datetime.combine( start_date, start_time or time(0, 0, 0) ) qualifying.append( (effective, int(row["EXSEQ"]), row, start_date, start_time) ) qualifying.sort(key=lambda item: (item[0], item[1])) trtsdt = trtsdtm = trtstmf = "" trtedt = trtedtm = trtetmf = "" trtdurd = "" if qualifying: _, _, first_row, start_date, start_time = qualifying[0] trt01a = first_row["EXTRT"].strip().upper() trtsdt = start_date.isoformat() trtsdtm = ( f"{start_date.isoformat()}T" f"{(start_time or time(0, 0, 0)).isoformat()}" ) trtstmf = "H" if start_time is None else "" else: actarm = (dm.get("ACTARM") or "").strip() trt01a = actarm.upper() if actarm else "NOT TREATED" # Latest end among records naming a treatment, with or without a # start; an end collected without a time counts as 23:59:59. end_candidates = [] for row in subject_ex: if row["EXTRT"].strip() not in NAMED_TREATMENTS: continue end_date, end_time, has_end = parse_dtc(row["EXENDTC"]) if has_end: effective = datetime.combine( end_date, end_time or time(23, 59, 59) ) end_candidates.append((effective, end_date, end_time)) if end_candidates: _, end_date, end_time = max( end_candidates, key=lambda item: item[0] ) trtedt = end_date.isoformat() trtedtm = ( f"{end_date.isoformat()}T" f"{(end_time or time(23, 59, 59)).isoformat()}" ) trtetmf = "H" if end_time is None else "" if trtsdt and trtedt: start = datetime.strptime(trtsdt, "%Y-%m-%d").date() end = datetime.strptime(trtedt, "%Y-%m-%d").date() trtdurd = str((end - start).days + 1) output_rows.append( { "STUDYID": dm["STUDYID"], "USUBJID": dm["USUBJID"], "TRT01A": trt01a, "TRTSDT": trtsdt, "TRTSDTM": trtsdtm, "TRTSTMF": trtstmf, "TRTEDT": trtedt, "TRTEDTM": trtedtm, "TRTETMF": trtetmf, "TRTDURD": trtdurd, "SAFFL": "Y" if trtsdt else "N", } ) with open(OUTPUT_PATH, "w", newline="") as handle: writer = csv.DictWriter(handle, fieldnames=COLUMNS) writer.writeheader() writer.writerows(output_rows)if __name__ == "__main__": main()solutions/adam-adsl-treatment/result.sas
Edit50 lines/* opensas reference solution for the yamaa benchmark adam-adsl-treatment. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data dm; length STUDYID USUBJID ACTARM $1024; infile "/app/input/dm.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. ACTARM : $char1024.;run;data ex; length STUDYID USUBJID EXTRT EXSTDTC EXENDTC $1024; infile "/app/input/ex.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. EXSEQ EXTRT : $char1024. EXDOSE EXSTDTC : $char1024. EXENDTC : $char1024.;run;data exposure; length startmoment endmoment $19; set ex; if upcase(EXTRT) in ('VITAMIN D3','PLACEBO'); startmoment=EXSTDTC; endmoment=EXENDTC; if lengthn(EXSTDTC)=10 then startmoment=cats(EXSTDTC,'T00:00:00'); else if lengthn(EXSTDTC)=16 then startmoment=cats(EXSTDTC,':00'); if lengthn(EXENDTC)=10 then endmoment=cats(EXENDTC,'T23:59:59'); else if lengthn(EXENDTC)=16 then endmoment=cats(EXENDTC,':00');run;proc sort data=exposure(where=(EXSTDTC ne '')) out=starts; by STUDYID USUBJID startmoment EXSEQ; run;data firstex; set starts; by STUDYID USUBJID; if first.USUBJID; run;proc sort data=exposure(where=(EXENDTC ne '')) out=ends; by STUDYID USUBJID descending endmoment; run;data lastex; set ends; by STUDYID USUBJID; if first.USUBJID; run;proc sql; create table joined as select a.*,b.EXTRT,b.EXSTDTC,b.startmoment,c.EXENDTC,c.endmoment from dm as a left join firstex as b on a.STUDYID=b.STUDYID and a.USUBJID=b.USUBJID left join lastex as c on a.STUDYID=c.STUDYID and a.USUBJID=c.USUBJID; quit;data result; length TRT01A $1024 TRTSDT TRTEDT $10 TRTSDTM TRTEDTM $19 TRTSTMF TRTETMF SAFFL $1; set joined; TRT01A=upcase(coalescec(EXTRT,ACTARM,'NOT TREATED')); TRTSDT=''; TRTEDT=''; TRTSTMF=''; TRTETMF=''; TRTDURD=.; if lengthn(EXSTDTC)>=10 then TRTSDT=substr(EXSTDTC,1,10); if lengthn(EXENDTC)>=10 then TRTEDT=substr(EXENDTC,1,10); TRTSDTM=tranwrd(startmoment,'T',' '); TRTEDTM=tranwrd(endmoment,'T',' '); if lengthn(EXSTDTC)=10 then TRTSTMF='H'; if lengthn(EXENDTC)=10 then TRTETMF='H'; if not missing(TRTSDT) and not missing(TRTEDT) then TRTDURD=input(TRTEDT,yymmdd10.)-input(TRTSDT,yymmdd10.)+1; SAFFL='N'; if not missing(TRTSDT) then SAFFL='Y';run;proc sql; create table final as select STUDYID, USUBJID, TRT01A, TRTSDT, TRTSDTM, TRTSTMF, TRTEDT, TRTEDTM, TRTETMF, TRTDURD, SAFFL from result;quit;proc export data=final outfile="/app/output/adsl.csv" dbms=csv replace; run;
yamaa