As a clinical trial statistician or programmer, challenge anything in this benchmark: describe a problem in Comments, or propose a fix with the Edit button on any source file.
- Task: Would a real study need this derivation, specified this way? Does it follow CDISC ADaM: variable names, controlled terms, record structure? Flag any rule that is ambiguous or that a sponsor would handle differently.
- Inputs: Do they look like data collected in a real trial, and do they include the situations you would expect to meet in one?
- Expected output: Would independent QC programming reproduce every value from these inputs and rules?
The other tabs beside Comments are background for assessment, not under review.
Summary
README.mdGoal: derive ANRIND, BASE, BNRIND, SHIFT1, R2BASE,
CRIT1, CRIT1FL, CRIT2, and CRIT2FL: mark where each analysis
value sits against its normal range, how that mark moved since
baseline, and whether the record met a high-result criterion or a
low-result criterion.
Input: laboratory records carrying the analysis value AVAL, the
normal range limits ANRLO and ANRHI, and the baseline flag
ABLFL (Y on the record taken as the baseline for the subject
and parameter).
Variables:
-
ANRINDis the record's own mark:LOWbelowANRLO,HIGHaboveANRHI, andNORMALbetween them, limits included, so a result exactly at a limit readsNORMAL; empty whenAVAL,ANRLO, orANRHIis missing, since one missing limit makes the mark unclassifiable. -
BASErepeats the baseline record'sAVALon every record of the subject and parameter; empty when no record carries the flag. -
BNRINDrepeats the baseline record'sANRINDthe same way; empty with no flagged baseline, or when the baseline record itself could not be marked. -
SHIFT1joins the baseline mark and the record's own mark, baseline first, so a result that stayed normal readsNORMAL to NORMALand one that moved out of range readsNORMAL to HIGH; empty when either mark is missing - the record's own or the baseline's. -
R2BASEdividesAVALbyBASE, so the baseline record itself reads 1 when the ratio can be computed; empty whenAVALis missing, when there is no baseline, and when the baseline is zero since the multiple is not defined there. -
CRIT1states the criterion the record was assessed against, a result greater than three times the upper limit of normal (ULN):Result greater than 3 x ULN; empty whenAVALorANRHIis missing, since the comparison cannot be made. -
CRIT1FLsays whether the record met it,YorN; empty where it could not be assessed, which differs from assessed and not met. A result exactly at three times the limit does not meet it - the comparison is strictly greater than. -
CRIT2states the second criterion the record was assessed against, a result less than the lower limit of normal (LLN):Result less than LLN; empty whenAVALorANRLOis missing, since the comparison cannot be made. It is assessed independently of the first: a record whose upper limit is missing can still meet the low criterion. -
CRIT2FLsays whether the record met it,YorN; empty where it could not be assessed. A result exactly at the lower limit does not meet it - the comparison is strictly less than.
Note: the shift joins the baseline mark with the record's own mark and the ratio rests on the flagged baseline value, while the mark and the criteria rest on the record's own value and limits; each criterion text and its flag always arrive together, as do the mark and the shift. A record that breaks these pairings stops the run, and no output is written.
Inputs
Under review1 source fileinput/adlb_raw.csv
Edit17 rows| STUDYID | USUBJID | PARAMCD | PARAM | ASEQ | AVISIT | AVAL | ANRLO | ANRHI | ABLFL |
|---|---|---|---|---|---|---|---|---|---|
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 1 | BASELINE | 30 | 0 | 40 | Y | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 2 | WEEK 2 | 60 | 0 | 40 | — | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 3 | WEEK 4 | 150 | 0 | 40 | — | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 4 | WEEK 8 | 40 | 0 | 40 | — | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 1 | BASELINE | 45 | 0 | 40 | Y | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 2 | WEEK 2 | 18 | 0 | 40 | — | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 3 | WEEK 4 | — | 0 | 40 | — | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 4 | WEEK 8 | 120 | 0 | 40 | — | |
| YAMAA-01 | EOS | Eosinophils (%) | 1 | BASELINE | 0 | 1 | 6 | Y | |
| YAMAA-01 | EOS | Eosinophils (%) | 2 | WEEK 2 | 4 | 1 | 6 | — | |
| YAMAA-01 | EOS | Eosinophils (%) | 3 | WEEK 4 | 1 | 1 | 6 | — | |
| YAMAA-01 | LDH | Lactate Dehydrogenase (U/L) | 3 | BASELINE | 200 | — | — | Y | |
| YAMAA-01 | LDH | Lactate Dehydrogenase (U/L) | 4 | WEEK 2 | 260 | — | — | — | |
| YAMAA-01 | GGT | Gamma Glutamyl Transferase (U/L) | 5 | BASELINE | 55 | 10 | — | Y | |
| YAMAA-01 | GGT | Gamma Glutamyl Transferase (U/L) | 6 | WEEK 2 | 70 | 10 | — | — | |
| YAMAA-01 | EOS | Eosinophils (%) | 4 | WEEK 8 | 0.5 | 1 | 6 | — | |
| YAMAA-01 | GGT | Gamma Glutamyl Transferase (U/L) | 7 | WEEK 4 | 5 | 10 | — | — |
Expected output
Under review17 expected rowsexpected/adlb.csv
Edit17 rows| STUDYID | USUBJID | PARAMCD | PARAM | ASEQ | AVISIT | AVAL | ANRLO | ANRHI | ANRIND | ABLFL | BASE | BNRIND | SHIFT1 | R2BASE | CRIT1 | CRIT1FL | CRIT2 | CRIT2FL |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 1 | BASELINE | 30 | 0 | 40 | NORMAL | Y | 30 | NORMAL | NORMAL to NORMAL | 1 | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 2 | WEEK 2 | 60 | 0 | 40 | HIGH | — | 30 | NORMAL | NORMAL to HIGH | 2 | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 3 | WEEK 4 | 150 | 0 | 40 | HIGH | — | 30 | NORMAL | NORMAL to HIGH | 5 | Result greater than 3 x ULN | Y | Result less than LLN | N | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 4 | WEEK 8 | 40 | 0 | 40 | NORMAL | — | 30 | NORMAL | NORMAL to NORMAL | 1.3333333333333333 | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 1 | BASELINE | 45 | 0 | 40 | HIGH | Y | 45 | HIGH | HIGH to HIGH | 1 | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 2 | WEEK 2 | 18 | 0 | 40 | NORMAL | — | 45 | HIGH | HIGH to NORMAL | 0.4 | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 3 | WEEK 4 | — | 0 | 40 | — | — | 45 | HIGH | — | — | — | — | — | — | |
| YAMAA-01 | ALT | Alanine Aminotransferase (U/L) | 4 | WEEK 8 | 120 | 0 | 40 | HIGH | — | 45 | HIGH | HIGH to HIGH | 2.6666666666666665 | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | EOS | Eosinophils (%) | 1 | BASELINE | 0 | 1 | 6 | LOW | Y | 0 | LOW | LOW to LOW | — | Result greater than 3 x ULN | N | Result less than LLN | Y | |
| YAMAA-01 | EOS | Eosinophils (%) | 2 | WEEK 2 | 4 | 1 | 6 | NORMAL | — | 0 | LOW | LOW to NORMAL | — | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | EOS | Eosinophils (%) | 3 | WEEK 4 | 1 | 1 | 6 | NORMAL | — | 0 | LOW | LOW to NORMAL | — | Result greater than 3 x ULN | N | Result less than LLN | N | |
| YAMAA-01 | LDH | Lactate Dehydrogenase (U/L) | 3 | BASELINE | 200 | — | — | — | Y | 200 | — | — | 1 | — | — | — | — | |
| YAMAA-01 | LDH | Lactate Dehydrogenase (U/L) | 4 | WEEK 2 | 260 | — | — | — | — | 200 | — | — | 1.3 | — | — | — | — | |
| YAMAA-01 | GGT | Gamma Glutamyl Transferase (U/L) | 5 | BASELINE | 55 | 10 | — | — | Y | 55 | — | — | 1 | — | — | Result less than LLN | N | |
| YAMAA-01 | GGT | Gamma Glutamyl Transferase (U/L) | 6 | WEEK 2 | 70 | 10 | — | — | — | 55 | — | — | 1.2727272727272727 | — | — | Result less than LLN | N | |
| YAMAA-01 | EOS | Eosinophils (%) | 4 | WEEK 8 | 0.5 | 1 | 6 | LOW | — | 0 | LOW | LOW to LOW | — | Result greater than 3 x ULN | N | Result less than LLN | Y | |
| YAMAA-01 | GGT | Gamma Glutamyl Transferase (U/L) | 7 | WEEK 4 | 5 | 10 | — | — | — | 55 | — | — | 0.09090909090909091 | — | — | Result less than LLN | Y |
Comments and assessment materials
| Dataset Name | Variable Name | Variable Label | Type | Codelist/Controlled Terms | Core | Computational Method | Origin |
|---|---|---|---|---|---|---|---|
| ADLB | STUDYID | Study Identifier | character | Copy value from ADLB_RAW.STUDYID. | Predecessor | ||
| ADLB | USUBJID | Unique Subject Identifier | character | Copy value from ADLB_RAW.USUBJID. | Predecessor | ||
| ADLB | PARAMCD | Parameter Code | character | Copy value from ADLB_RAW.PARAMCD. | Predecessor | ||
| ADLB | PARAM | Parameter | character | Copy value from ADLB_RAW.PARAM. | Predecessor | ||
| ADLB | ASEQ | Analysis Sequence Number | numeric | Copy value from ADLB_RAW.ASEQ. | Predecessor | ||
| ADLB | AVISIT | Analysis Visit | character | Copy value from ADLB_RAW.AVISIT. | Predecessor | ||
| ADLB | AVAL | Analysis Value | numeric | Copy value from ADLB_RAW.AVAL. | Predecessor | ||
| ADLB | ANRLO | Analysis Normal Range Lower Limit | numeric | Copy value from ADLB_RAW.ANRLO. | Predecessor | ||
| ADLB | ANRHI | Analysis Normal Range Upper Limit | numeric | Copy value from ADLB_RAW.ANRHI. | Predecessor | ||
| ADLB | ANRIND | Analysis Reference Range Indicator | character | LOW, NORMAL, HIGH | If AVAL IS NULL OR ANRLO IS NULL OR ANRHI IS NULL then "None"; If AVAL < ANRLO then "LOW"; If AVAL > ANRHI then "HIGH"; otherwise "NORMAL". | Derived | |
| ADLB | ABLFL | Baseline Record Flag | character | Y | Copy value from ADLB_RAW.ABLFL. | Predecessor | |
| ADLB | BASE | Baseline Value | numeric | Aggregate ONLY(AVAL) over records grouped by STUDYID, USUBJID, PARAMCD, matching on the shared output keys, where ABLFL = 'Y'. | Derived | ||
| ADLB | BNRIND | Baseline Reference Range Indicator | character | LOW, NORMAL, HIGH | Aggregate ONLY(ANRIND) over records grouped by STUDYID, USUBJID, PARAMCD, matching on the shared output keys, where ABLFL = 'Y'. | Derived | |
| ADLB | SHIFT1 | Shift 1 | character | Fill the template "{BNRIND} to {ANRIND}"; a missing field → blank. | Derived | ||
| ADLB | R2BASE | Ratio to Baseline | numeric | Compute AVAL / NULLIF(BASE, 0). | Derived | ||
| ADLB | CRIT1 | Analysis Criterion 1 | character | If AVAL IS NOT NULL AND CRITLIM IS NOT NULL then "Result greater than 3 x ULN"; otherwise blank. | Derived | ||
| ADLB | CRIT1FL | Criterion 1 Evaluation Result Flag | character | Y, N | If AVAL IS NULL OR CRITLIM IS NULL then "None"; If AVAL > CRITLIM then "Y"; otherwise "N". | Derived | |
| ADLB | CRIT2 | Analysis Criterion 2 | character | If AVAL IS NOT NULL AND ANRLO IS NOT NULL then "Result less than LLN"; otherwise blank. | Derived | ||
| ADLB | CRIT2FL | Criterion 2 Evaluation Result Flag | character | Y, N | If AVAL IS NULL OR ANRLO IS NULL then "None"; If AVAL < ANRLO then "Y"; otherwise "N". | Derived |
| Variable | Permitted values |
|---|---|
| ANRIND | LOW, NORMAL, HIGH |
| ABLFL | Y |
| BNRIND | LOW, NORMAL, HIGH |
| CRIT1FL | Y, N |
| CRIT2FL | Y, N |
| Version | Date | Author | Description | Reviewer | Sign-off |
|---|---|---|---|---|---|
| 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-adlb-shift-criteria/full.md
Edit44 linesFollowing CDISC ADaM standards, use the provided ADLB_RAW dataset to create an ADLB dataset with one record per laboratory record.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, PARAMCD, PARAM, ASEQ, AVISIT, AVAL, ANRLO, ANRHI, ANRIND, ABLFL, BASE, BNRIND, SHIFT1, R2BASE, CRIT1, CRIT1FL, CRIT2, CRIT2FL
ANRIND is the record's own mark: LOW below the lower limit, HIGH above the upper limit, and NORMAL between them, limits included, so a result exactly at a limit reads NORMAL. It has no value when the result or either limit is missing.
BASE repeats the flagged baseline record's value on every record of the subject and parameter; it has no value when no record carries the flag. BNRIND repeats the baseline record's mark the same way; it has no value with no flagged baseline, or when the baseline record itself could not be marked.
SHIFT1 joins the baseline mark and the record's own mark, baseline first, so a result that stayed normal reads "NORMAL to NORMAL". It has no value when either mark is missing.
R2BASE is the record's value as a multiple of the baseline value, not rounded, so the baseline record itself reads 1 when the ratio can be computed. It has no value when the record's value is missing, when there is no baseline, or when the baseline is zero.
CRIT1 states the criterion the record was assessed against, a result greater than three times the upper limit of normal (ULN): "Result greater than 3 x ULN". It has no value when the result or the upper limit is missing. CRIT1FL says whether the record met it, Y or N; it has no value where it could not be assessed. A result exactly at three times the limit does not meet it.
CRIT2 states a second criterion, a result less than the lower limit of normal (LLN): "Result less than LLN". It has no value when the result or the lower limit is missing, and it is assessed independently of the first criterion. CRIT2FL says whether the record met it, Y or N; it has no value where it could not be assessed. A result exactly at the lower limit does not meet it.
Read the source datasets from /app/input and save the completed dataset as /app/output/adlb.csv.
prompts/adam-adlb-shift-criteria/conventions.md
Edit20 linesFollowing CDISC ADaM standards, use the provided ADLB_RAW dataset to create an ADLB dataset with one record per laboratory record.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, PARAMCD, PARAM, ASEQ, AVISIT, AVAL, ANRLO, ANRHI, ANRIND, ABLFL, BASE, BNRIND, SHIFT1, R2BASE, CRIT1, CRIT1FL, CRIT2, CRIT2FL
ANRIND is LOW, HIGH, or NORMAL, or has no value.
SHIFT1 joins the baseline mark and the record's own mark, baseline first.
R2BASE is not rounded.
CRIT1 is "Result greater than 3 x ULN" or has no value. CRIT1FL is Y or N, or has no value. CRIT2 is "Result less than LLN" or has no value. CRIT2FL is Y or N, or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/adlb.csv.
prompts/adam-adlb-shift-criteria/brief.md
Edit10 linesFollowing CDISC ADaM standards, use the provided ADLB_RAW dataset to create an ADLB dataset with one record per laboratory record.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, PARAMCD, PARAM, ASEQ, AVISIT, AVAL, ANRLO, ANRHI, ANRIND, ABLFL, BASE, BNRIND, SHIFT1, R2BASE, CRIT1, CRIT1FL, CRIT2, CRIT2FL
Read the source datasets from /app/input and save the completed dataset as /app/output/adlb.csv.
run.R
Edit4 lineslibrary(yamaa)adlb <- yamaa_domain("spec.yaml")$outputadlbrun.py
Edit4 linesimport yamaaadlb = yamaa.yamaa_domain("spec.yaml").outputadlbsolutions/adam-adlb-shift-criteria/result.R
Edit88 lines# Reference solution for the yamaa benchmark adam-adlb-shift-criteria (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)raw <- read_csv( "/app/input/adlb_raw.csv", col_types = cols( ASEQ = col_integer(), AVAL = col_double(), ANRLO = col_double(), ANRHI = col_double(), .default = col_character() ))# The record's own mark: LOW below the lower limit, HIGH above the upper# limit, NORMAL between them limits included. No value when the result or# either limit is missing.based <- raw |> mutate( ANRIND = case_when( is.na(AVAL) | is.na(ANRLO) | is.na(ANRHI) ~ NA_character_, AVAL < ANRLO ~ "LOW", AVAL > ANRHI ~ "HIGH", .default = "NORMAL" ) )# BASE repeats the flagged baseline record's value; BNRIND repeats its# mark. Both have no value when no record carries the flag.baselines <- based |> filter(ABLFL %in% "Y") |> select(STUDYID, USUBJID, PARAMCD, BASE = AVAL, BNRIND = ANRIND)with_base <- based |> left_join(baselines, by = c("STUDYID", "USUBJID", "PARAMCD"))# SHIFT1 joins the baseline mark and the record's own mark; R2BASE is the# record as a multiple of the baseline; CRIT1 assesses greater than three# times the upper limit; CRIT2 assesses less than the lower limit.adlb <- with_base |> mutate( SHIFT1 = if_else( is.na(BNRIND) | is.na(ANRIND), NA_character_, paste(BNRIND, "to", ANRIND) ), R2BASE = if_else( is.na(AVAL) | is.na(BASE) | BASE == 0, NA_real_, AVAL / BASE ), CRITLIM = 3 * ANRHI, CRIT1 = if_else( !is.na(AVAL) & !is.na(CRITLIM), "Result greater than 3 x ULN", NA_character_ ), CRIT1FL = case_when( is.na(AVAL) | is.na(CRITLIM) ~ NA_character_, AVAL > CRITLIM ~ "Y", .default = "N" ), CRIT2 = if_else( !is.na(AVAL) & !is.na(ANRLO), "Result less than LLN", NA_character_ ), CRIT2FL = case_when( is.na(AVAL) | is.na(ANRLO) ~ NA_character_, AVAL < ANRLO ~ "Y", .default = "N" ) ) |> arrange(USUBJID, ASEQ) |> select( STUDYID, USUBJID, PARAMCD, PARAM, ASEQ, AVISIT, AVAL, ANRLO, ANRHI, ANRIND, ABLFL, BASE, BNRIND, SHIFT1, R2BASE, CRIT1, CRIT1FL, CRIT2, CRIT2FL )dir.create("/app/output", showWarnings = FALSE)write_csv(adlb, "/app/output/adlb.csv", na = "")solutions/adam-adlb-shift-criteria/result.py
Edit115 lines# Reference solution for the yamaa benchmark adam-adlb-shift-criteria (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.from pathlib import Pathimport polars as plraw = pl.read_csv("/app/input/adlb_raw.csv", infer_schema=False).with_columns( pl.col("ASEQ").cast(pl.Int64), pl.col("AVAL").cast(pl.Float64, strict=False), pl.col("ANRLO").cast(pl.Float64, strict=False), pl.col("ANRHI").cast(pl.Float64, strict=False),)# The record's own mark: LOW below the lower limit, HIGH above the upper# limit, NORMAL between them limits included. No value when the result or# either limit is missing.based = raw.with_columns( ANRIND=pl.when( pl.col("AVAL").is_null() | pl.col("ANRLO").is_null() | pl.col("ANRHI").is_null() ) .then(None) .when(pl.col("AVAL") < pl.col("ANRLO")) .then(pl.lit("LOW")) .when(pl.col("AVAL") > pl.col("ANRHI")) .then(pl.lit("HIGH")) .otherwise(pl.lit("NORMAL")),)# BASE repeats the flagged baseline record's value; BNRIND repeats its# mark. Both have no value when no record carries the flag.baselines = ( based.filter(pl.col("ABLFL") == "Y") .select("STUDYID", "USUBJID", "PARAMCD", BASE="AVAL", BNRIND="ANRIND"))with_base = based.join( baselines, on=["STUDYID", "USUBJID", "PARAMCD"], how="left")# SHIFT1 joins the baseline mark and the record's own mark; R2BASE is the# record as a multiple of the baseline; CRIT1 assesses greater than three# times the upper limit; CRIT2 assesses less than the lower limit.adlb = ( with_base.with_columns( SHIFT1=pl.when( pl.col("BNRIND").is_null() | pl.col("ANRIND").is_null() ) .then(None) .otherwise(pl.col("BNRIND") + pl.lit(" to ") + pl.col("ANRIND")), R2BASE=pl.when( pl.col("AVAL").is_null() | pl.col("BASE").is_null() | (pl.col("BASE") == 0) ) .then(None) .otherwise(pl.col("AVAL") / pl.col("BASE")), CRITLIM=3 * pl.col("ANRHI"), ) .with_columns( CRIT1=pl.when( pl.col("AVAL").is_not_null() & pl.col("CRITLIM").is_not_null() ) .then(pl.lit("Result greater than 3 x ULN")) .otherwise(None), CRIT1FL=pl.when( pl.col("AVAL").is_null() | pl.col("CRITLIM").is_null() ) .then(None) .when(pl.col("AVAL") > pl.col("CRITLIM")) .then(pl.lit("Y")) .otherwise(pl.lit("N")), CRIT2=pl.when( pl.col("AVAL").is_not_null() & pl.col("ANRLO").is_not_null() ) .then(pl.lit("Result less than LLN")) .otherwise(None), CRIT2FL=pl.when( pl.col("AVAL").is_null() | pl.col("ANRLO").is_null() ) .then(None) .when(pl.col("AVAL") < pl.col("ANRLO")) .then(pl.lit("Y")) .otherwise(pl.lit("N")), ) .select( "STUDYID", "USUBJID", "PARAMCD", "PARAM", "ASEQ", "AVISIT", "AVAL", "ANRLO", "ANRHI", "ANRIND", "ABLFL", "BASE", "BNRIND", "SHIFT1", "R2BASE", "CRIT1", "CRIT1FL", "CRIT2", "CRIT2FL", ) .sort(["USUBJID", "ASEQ"]))Path("/app/output").mkdir(exist_ok=True)adlb.write_csv("/app/output/adlb.csv")solutions/adam-adlb-shift-criteria/result.sas
Edit35 lines/* opensas reference solution for the yamaa benchmark adam-adlb-shift-criteria. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data adlb_raw; length STUDYID USUBJID PARAMCD PARAM AVISIT ABLFL $1024; infile "/app/input/adlb_raw.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. PARAMCD : $char1024. PARAM : $char1024. ASEQ AVISIT : $char1024. AVAL ANRLO ANRHI ABLFL : $char1024.;run;data marked; length ANRIND $6; set adlb_raw; if not missing(AVAL) and not missing(ANRLO) and not missing(ANRHI) then do; if AVAL<ANRLO then ANRIND='LOW'; else if AVAL>ANRHI then ANRIND='HIGH'; else ANRIND='NORMAL'; end;run;proc sql; create table combined as select a.*,b.AVAL as BASE,b.ANRIND as BNRIND from marked as a left join marked as b on a.STUDYID=b.STUDYID and a.USUBJID=b.USUBJID and a.PARAMCD=b.PARAMCD and b.ABLFL='Y'; quit;data result; length SHIFT1 $20 CRIT1 $30 CRIT2 $30 CRIT1FL CRIT2FL $1; set combined; if not missing(ANRIND) and not missing(BNRIND) then SHIFT1=catx(' to ',BNRIND,ANRIND); if not missing(AVAL) and not missing(BASE) and BASE ne 0 then R2BASE=AVAL/BASE; if not missing(AVAL) and not missing(ANRHI) then do; CRIT1='Result greater than 3 x ULN'; CRIT1FL='N'; if AVAL>3*ANRHI then CRIT1FL='Y'; end; if not missing(AVAL) and not missing(ANRLO) then do; CRIT2='Result less than LLN'; CRIT2FL='N'; if AVAL<ANRLO then CRIT2FL='Y'; end;run;proc sql; create table final as select STUDYID, USUBJID, PARAMCD, PARAM, ASEQ, AVISIT, AVAL, ANRLO, ANRHI, ANRIND, ABLFL, BASE, BNRIND, SHIFT1, R2BASE, CRIT1, CRIT1FL, CRIT2, CRIT2FL from result;quit;proc export data=final outfile="/app/output/adlb.csv" dbms=csv replace; run;
yamaa
Comments
Signed in with GitHub; saved in repository Discussions