Review ask

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.

  1. 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.
  2. Inputs: Do they look like data collected in a real trial, and do they include the situations you would expect to meet in one?
  3. 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

Lifecycle: draftEditUnder review
What this benchmark means
README.md

Goal: compute visit-level measures with every window expression over one shared ordering: sequence numbering with a filter, competition and dense ranking, reading a neighboring row with and without a filter, the last non-missing value, the carried-forward value, and the baseline visit flag.

Input: VS carries one row per visit: subject, visit number (VISITN), visit date (VSDTC), treatment start date (TRTSDT), the result (VSSTRESN), and whether the visit is evaluable (VSEVAL), all carried through unchanged.

Windows:

  • VSSEQ numbers the evaluable visits from 1 within each subject in visit order; a visit that is not evaluable is left out before numbering and gets missing.
  • SEVRANKC ranks each subject's results highest first with competition numbering: the two tied visits of subject 01 share rank 1 and the next value takes rank 3, skipping a position. SEVRANKD ranks the same ordering densely, so no number is skipped. Missing results rank after every present one and tie with each other, so the two missing results of subject 02 share one rank.
  • PREVRES reads the previous visit's result and NEXTRES the next visit's. A missing result is not skipped: subject 01 visit 4 gets a missing previous result because visit 3's result is missing, just as a first visit does because nothing precedes it.
  • EVALPREV reads the previous evaluable visit's result. The visits that are not evaluable are left out before stepping back, so subject 01 visit 4 reads visit 2's result across visit 3, and a visit that is not evaluable gets missing.
  • LASTRES is the closest strictly earlier non-missing result, crossing any number of consecutive gaps: subject 02 visit 4 reads the visit 1 result across two missing visits. The current visit is never a candidate, so a visit with a result still reads its predecessor's.
  • CARRYRES returns the current result when present and otherwise the closest strictly earlier non-missing result. It differs from LASTRES only where the current visit has a result: a first visit with a result keeps it instead of reading missing.
  • BLFL marks the latest visit dated on or before treatment start; two visits sharing that latest date stop the run rather than one being picked. The baseline visit can carry a missing result (subject 02 visit 2); a subject with no visit on or before treatment start (subject 04) has no baseline.

Note: only VSSEQ and EVALPREV leave out the visits that are not evaluable. Every other measure sees every visit, so a visit that is not evaluable is still ranked, read as a neighbor, and can be the baseline visit.

Inputs

Under review
1 source file

input/vs.csv

Edit
13 rows
input/vs.csv
STUDYIDUSUBJIDVISITNVISITVSDTCTRTSDTVSSTRESNVSEVAL
YAMAA-011VISIT 12025-01-022025-01-12120Y
YAMAA-012VISIT 22025-01-092025-01-12118Y
YAMAA-013VISIT 32025-01-162025-01-12—N
YAMAA-014VISIT 42025-01-232025-01-12122Y
YAMAA-015VISIT 52025-01-302025-01-12122Y
YAMAA-011VISIT 12025-02-012025-02-1098Y
YAMAA-012VISIT 22025-02-082025-02-10—Y
YAMAA-013VISIT 32025-02-152025-02-10—Y
YAMAA-014VISIT 42025-02-222025-02-10105Y
YAMAA-011VISIT 12025-03-012025-03-20130Y
YAMAA-012VISIT 22025-03-082025-03-20130Y
YAMAA-013VISIT 32025-03-152025-03-20128N
YAMAA-011VISIT 12025-04-012025-03-15115Y

Expected output

Under review
13 expected rows

expected/advs.csv

Edit
13 rows
expected/advs.csv
STUDYIDUSUBJIDVISITNVISITVSDTCTRTSDTVSSTRESNVSEVALVSSEQSEVRANKCSEVRANKDPREVRESNEXTRESEVALPREVLASTRESCARRYRESBLFL
YAMAA-011VISIT 12025-01-022025-01-12120Y132—118——120—
YAMAA-012VISIT 22025-01-092025-01-12118Y243120—120120118Y
YAMAA-013VISIT 32025-01-162025-01-12—N—54118122—118118—
YAMAA-014VISIT 42025-01-232025-01-12122Y311—122118118122—
YAMAA-015VISIT 52025-01-302025-01-12122Y411122—122122122—
YAMAA-011VISIT 12025-02-012025-02-1098Y122————98—
YAMAA-012VISIT 22025-02-082025-02-10—Y23398—989898Y
YAMAA-013VISIT 32025-02-152025-02-10—Y333—105—9898—
YAMAA-014VISIT 42025-02-222025-02-10105Y411———98105—
YAMAA-011VISIT 12025-03-012025-03-20130Y111—130——130—
YAMAA-012VISIT 22025-03-082025-03-20130Y211130128130130130—
YAMAA-013VISIT 32025-03-152025-03-20128N—32130——130128Y
YAMAA-011VISIT 12025-04-012025-03-15115Y111————115—
Shaded columns are derived— = missing value

Comments and assessment materials

Comments

Signed in with GitHub; saved in repository Discussions

Mapping spec

Generated from the benchmark YAML; do not edit by hand

Dataset NameVariable NameVariable LabelTypeCodelist/Controlled TermsCoreComputational MethodOrigin
ADVSSTUDYIDStudy IdentifiercharacterCopy value from VS.STUDYID.Predecessor
ADVSUSUBJIDUnique Subject IdentifiercharacterCopy value from VS.USUBJID.Predecessor
ADVSVISITNVisit NumbernumericCopy value from VS.VISITN.Predecessor
ADVSVISITVisit NamecharacterCopy value from VS.VISIT.Predecessor
ADVSVSDTCVisit DatenumericISO 8601Copy value from VS.VSDTC.Predecessor
ADVSTRTSDTTreatment Start DatenumericISO 8601Copy value from VS.TRTSDT.Predecessor
ADVSVSSTRESNResult in Numeric FormatnumericCopy value from VS.VSSTRESN.Predecessor
ADVSVSEVALEvaluable Visit FlagcharacterCopy value from VS.VSEVAL.Predecessor
ADVSVSSEQEvaluable Visit Sequence NumbernumericRow number within each group of USUBJID, ordered by VISITN.Derived
ADVSSEVRANKCCompetition Rank of ResultnumericRank rows from 1 using window RESULT_ORDER; ties share a number and the next distinct value skips the gap.Derived
ADVSSEVRANKDDense Rank of ResultnumericRank rows from 1 using window RESULT_ORDER; ties share a number and the next distinct value follows without a gap.Derived
ADVSPREVRESPrevious Visit ResultnumericTake VSSTRESN from 1 row earlier using window VISIT_ORDER.Derived
ADVSNEXTRESNext Visit ResultnumericTake VSSTRESN from 1 row later using window VISIT_ORDER.Derived
ADVSEVALPREVPrevious Evaluable Visit ResultnumericTake VSSTRESN from 1 row earlier within each group of USUBJID, ordered by VISITN, over rows where VSEVAL = 'Y'.Derived
ADVSLASTRESLast Non-missing ResultnumericMost recent non-missing VSSTRESN from an earlier row using window VISIT_ORDER.Derived
ADVSCARRYRESCarried-forward ResultnumericLast observation carried forward from VSSTRESN using window VISIT_ORDER.Derived
ADVSBLFLBaseline Visit Flagcharacter"Y" for the last record with VSDTC on or before TRTSDT within each group of USUBJID; blank otherwise.Derived
VersionDateAuthorDescriptionReviewerSign-off
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

yamaa code

Runs the yamaa specification; its result must match the expected output

run.R

Edit
4 lines
library(yamaa)advs <- yamaa_domain("spec.yaml")$outputadvs

run.py

Edit
4 lines
import yamaaadvs = yamaa.yamaa_domain("spec.yaml").outputadvs