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: derive VSSEQ, VSTESTCD, VSTEST, VSORRES, VSORRESU,
VSSTAT, VSREASND, VSDTC, VSTPT, VSTPTNUM, VSTPTREF and
VSRFTDTC for every day of the temperature diary after each vaccination in
Vital Signs (VS), including the days no temperature was entered.
Input: the vaccination log, one record per planned vaccination with its date when given; the protocol's diary period, one record per diary day with its label; and the e-diary transfer, one record per temperature entered, with its date and unit.
Variables:
VSSEQnumbers the subject's records by vaccination date, then diary day.VSTESTCDis alwaysTEMP.VSTESTis alwaysTemperature.VSORRESis the temperature entered on the diary date, empty on a day with no entry.VSORRESUis the unit of the temperature entered, empty on a day with no entry.VSSTATisNOT DONEon a diary day with no temperature entered, and empty otherwise.VSREASNDisNOT ENTEREDon a day markedNOT DONE, and empty otherwise.VSDTCis the diary date: the vaccination date on Day 1, one day later for each later diary day.VSTPTis the diary day's label (DAY 1, ...).VSTPTNUMis the diary day's number, 1 on the day of vaccination.VSTPTREFnames the vaccination the diary day follows.VSRFTDTCis that vaccination's date.
Note: every vaccination that was given expects one record for each day of the diary period, whether or not the e-diary holds a temperature for it. A vaccination with no date was not given and expects no diary records.
Inputs
Under review3 source filesinput/diary_days.csv
Edit7 rows| STUDYID | DIARYDAY | DAYLABEL |
|---|---|---|
| VAX02 | 1 | DAY 1 |
| VAX02 | 2 | DAY 2 |
| VAX02 | 3 | DAY 3 |
| VAX02 | 4 | DAY 4 |
| VAX02 | 5 | DAY 5 |
| VAX02 | 6 | DAY 6 |
| VAX02 | 7 | DAY 7 |
input/temperature.csv
Edit16 rows| STUDYID | USUBJID | TEMPDAT | TEMP | TEMPU |
|---|---|---|---|---|
| VAX02 | 2023-01-01 | 36.8 | C | |
| VAX02 | 2023-01-02 | 37.1 | C | |
| VAX02 | 2023-01-04 | 36.9 | C | |
| VAX02 | 2023-01-05 | 37.0 | C | |
| VAX02 | 2023-01-06 | 36.7 | C | |
| VAX02 | 2023-01-07 | 37.2 | C | |
| VAX02 | 2023-02-27 | 36.6 | C | |
| VAX02 | 2023-02-28 | 37.4 | C | |
| VAX02 | 2023-03-01 | 38.1 | C | |
| VAX02 | 2023-03-02 | 37.0 | C | |
| VAX02 | 2023-03-03 | 36.9 | C | |
| VAX02 | 2023-03-04 | 36.8 | C | |
| VAX02 | 2023-03-05 | 36.7 | C | |
| VAX02 | 2023-03-29 | 37.9 | C | |
| VAX02 | 2023-03-06 | 36.5 | C | |
| VAX02 | 2023-03-07 | 36.9 | C |
input/vaccination.csv
Edit5 rows| STUDYID | USUBJID | DOSENUM | VISIT | VACDAT |
|---|---|---|---|---|
| VAX02 | 1 | VACCINATION 1 | 2023-01-01 | |
| VAX02 | 1 | VACCINATION 1 | 2023-02-27 | |
| VAX02 | 2 | VACCINATION 2 | 2023-03-27 | |
| VAX02 | 1 | VACCINATION 1 | 2023-03-06 | |
| VAX02 | 2 | VACCINATION 2 | — |
Expected output
Under review28 expected rowsexpected/vs.csv
Edit28 rows| DOMAIN | STUDYID | USUBJID | VSSEQ | VSTESTCD | VSTEST | VSORRES | VSORRESU | VSSTAT | VSREASND | VSDTC | VSTPT | VSTPTNUM | VSTPTREF | VSRFTDTC |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| VS | VAX02 | 1 | TEMP | Temperature | 36.8 | C | — | — | 2023-01-01 | DAY 1 | 1 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 2 | TEMP | Temperature | 37.1 | C | — | — | 2023-01-02 | DAY 2 | 2 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 3 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-01-03 | DAY 3 | 3 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 4 | TEMP | Temperature | 36.9 | C | — | — | 2023-01-04 | DAY 4 | 4 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 5 | TEMP | Temperature | 37.0 | C | — | — | 2023-01-05 | DAY 5 | 5 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 6 | TEMP | Temperature | 36.7 | C | — | — | 2023-01-06 | DAY 6 | 6 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 7 | TEMP | Temperature | 37.2 | C | — | — | 2023-01-07 | DAY 7 | 7 | VACCINATION 1 | 2023-01-01 | |
| VS | VAX02 | 1 | TEMP | Temperature | 36.6 | C | — | — | 2023-02-27 | DAY 1 | 1 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 2 | TEMP | Temperature | 37.4 | C | — | — | 2023-02-28 | DAY 2 | 2 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 3 | TEMP | Temperature | 38.1 | C | — | — | 2023-03-01 | DAY 3 | 3 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 4 | TEMP | Temperature | 37.0 | C | — | — | 2023-03-02 | DAY 4 | 4 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 5 | TEMP | Temperature | 36.9 | C | — | — | 2023-03-03 | DAY 5 | 5 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 6 | TEMP | Temperature | 36.8 | C | — | — | 2023-03-04 | DAY 6 | 6 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 7 | TEMP | Temperature | 36.7 | C | — | — | 2023-03-05 | DAY 7 | 7 | VACCINATION 1 | 2023-02-27 | |
| VS | VAX02 | 8 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-27 | DAY 1 | 1 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 9 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-28 | DAY 2 | 2 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 10 | TEMP | Temperature | 37.9 | C | — | — | 2023-03-29 | DAY 3 | 3 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 11 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-30 | DAY 4 | 4 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 12 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-31 | DAY 5 | 5 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 13 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-04-01 | DAY 6 | 6 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 14 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-04-02 | DAY 7 | 7 | VACCINATION 2 | 2023-03-27 | |
| VS | VAX02 | 1 | TEMP | Temperature | 36.5 | C | — | — | 2023-03-06 | DAY 1 | 1 | VACCINATION 1 | 2023-03-06 | |
| VS | VAX02 | 2 | TEMP | Temperature | 36.9 | C | — | — | 2023-03-07 | DAY 2 | 2 | VACCINATION 1 | 2023-03-06 | |
| VS | VAX02 | 3 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-08 | DAY 3 | 3 | VACCINATION 1 | 2023-03-06 | |
| VS | VAX02 | 4 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-09 | DAY 4 | 4 | VACCINATION 1 | 2023-03-06 | |
| VS | VAX02 | 5 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-10 | DAY 5 | 5 | VACCINATION 1 | 2023-03-06 | |
| VS | VAX02 | 6 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-11 | DAY 6 | 6 | VACCINATION 1 | 2023-03-06 | |
| VS | VAX02 | 7 | TEMP | Temperature | — | — | NOT DONE | NOT ENTERED | 2023-03-12 | DAY 7 | 7 | VACCINATION 1 | 2023-03-06 |
Human review and assessment
| Variable Name | Variable Label | Type | Length | Controlled Terms or Format | Origin | Core | Conversion Definition | Variable Type | Variable Order | Comments for Define |
|---|---|---|---|---|---|---|---|---|---|---|
| DOMAIN | Domain Abbreviation | Char | Assigned | Set constant value "VS". | SDTM | 1 | ||||
| STUDYID | Study Identifier | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 2 | ||||
| USUBJID | Unique Subject Identifier | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 3 | ||||
| VSTESTCD | Vital Signs Test Short Name | Char | Assigned | Set constant value "TEMP". | SDTM | 4 | ||||
| VSTEST | Vital Signs Test Name | Char | Assigned | Set constant value "Temperature". | SDTM | 5 | ||||
| VSDTC | Date/Time of Measurements | Char | ISO 8601 | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 6 | |||
| VSTPT | Planned Time Point Name | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 7 | ||||
| VSTPTNUM | Planned Time Point Number | Num | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 8 | ||||
| VSTPTREF | Time Point Reference | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 9 | ||||
| VSRFTDTC | Date/Time of Reference Time Point | Char | ISO 8601 | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 10 | |||
| VSORRES | Result or Finding in Original Units | Char | Derived | Take TEMP from the TEMP record whose USUBJID equals USUBJID and TEMPDAT equals VSDTC, and no match yields blank. | SDTM | 11 | ||||
| VSORRESU | Original Units | Char | Derived | Take TEMPU from the TEMP record whose USUBJID equals USUBJID and TEMPDAT equals VSDTC, and no match yields blank. | SDTM | 12 | ||||
| VSSTAT | Completion Status | Char | NOT DONE | Derived | If TEMP IS NULL, with TEMP taken from the TEMP record whose USUBJID equals USUBJID and TEMPDAT equals VSDTC, and no match yields blank then "NOT DONE"; otherwise blank. | SDTM | 13 | |||
| VSREASND | Reason Not Performed | Char | Derived | If TEMP IS NULL, with TEMP taken from the TEMP record whose USUBJID equals USUBJID and TEMPDAT equals VSDTC, and no match yields blank then "NOT ENTERED"; otherwise blank. | SDTM | 14 | ||||
| VSSEQ | Sequence Number | Num | Derived | Row number within each group of STUDYID, USUBJID, ordered by VSRFTDTC then VSTPTNUM. | SDTM | 15 |
| Template | Include when | STUDYID | USUBJID | VSDTC | VSTPT | VSTPTNUM | VSTPTREF | VSRFTDTC |
|---|---|---|---|---|---|---|---|---|
| diary | VSRFTDTC IS NOT NULL | Copy STUDYID from the VAC record matching on STUDYID, where STUDYID is derived as VAC.STUDYID, and no match yields blank | Copy USUBJID from the VAC record matching on STUDYID, where USUBJID is derived as VAC.USUBJID, and no match yields blank | Copy DIARYDAT from the VAC record matching on STUDYID, where DIARYDAT is derived as the date VAC.VACDAT plus OFFSET days, and no match yields blank | Copy DAYLABEL from the VAC record matching on STUDYID, where DAYLABEL is derived as DAYS.DAYLABEL, and no match yields blank | Copy DIARYDAY from the VAC record matching on STUDYID, where DIARYDAY is derived as DAYS.DIARYDAY, and no match yields blank | Copy VISIT from the VAC record matching on STUDYID, where VISIT is derived as VAC.VISIT, and no match yields blank | Copy VACDAT from the VAC record matching on STUDYID, where VACDAT is derived as VAC.VACDAT, and no match yields blank |
| Variable | Permitted values |
|---|---|
| VSSTAT | NOT DONE |
| 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/sdtm-vs-diary-missed-days/full.md
Edit34 linesFollowing CDISC SDTM standards, use the provided DIARY_DAYS, TEMPERATURE, and VACCINATION datasets to create a VS dataset with one record per subject per vaccination given per day of the temperature diary period.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, VSSEQ, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSSTAT, VSREASND, VSDTC, VSTPT, VSTPTNUM, VSTPTREF, VSRFTDTC
DOMAIN is "VS". STUDYID and USUBJID are as VACCINATION gives them.
Every vaccination that was given has one record for each diary day listed in DIARY_DAYS, whether or not a temperature was entered for that day. A vaccination with no date in VACCINATION was not given and has no records.
- VSTESTCD is "TEMP" and VSTEST is "Temperature" on every record.
- VSTPTNUM is the diary day's number and VSTPT its label, as DIARY_DAYS gives them ("DAY 1", ...); day 1 is the day of vaccination.
- VSTPTREF is the visit name of the vaccination the diary day follows, as VACCINATION gives it (such as "VACCINATION 1"), and VSRFTDTC is that vaccination's date.
- VSDTC is the diary date: the vaccination date on day 1, and one calendar day later for each later diary day.
- A temperature was entered for a diary day when TEMPERATURE holds a record for the same subject dated on that diary date.
- VSORRES is that temperature and VSORRESU its unit, each as text exactly as TEMPERATURE writes it, so a reading written with a trailing zero keeps it. Both have no value on a diary day with no temperature entered.
- VSSTAT is "NOT DONE" and VSREASND is "NOT ENTERED" on a diary day with no temperature entered; both have no value otherwise.
- VSSEQ numbers each subject's records from 1, in order of vaccination date and then diary day number.
Read the source datasets from /app/input and save the completed dataset as /app/output/vs.csv.
prompts/sdtm-vs-diary-missed-days/conventions.md
Edit17 linesFollowing CDISC SDTM standards, use the provided DIARY_DAYS, TEMPERATURE, and VACCINATION datasets to create a VS dataset with one record per subject per vaccination given per day of the temperature diary period.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, VSSEQ, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSSTAT, VSREASND, VSDTC, VSTPT, VSTPTNUM, VSTPTREF, VSRFTDTC
DOMAIN is "VS", VSTESTCD is "TEMP" and VSTEST is "Temperature" on every record. VSTPT is a diary day label as DIARY_DAYS gives it ("DAY 1", ...); day 1 is the day of vaccination. VSTPTREF is a vaccination's visit name, such as "VACCINATION 1". VSORRES is text exactly as TEMPERATURE writes it, so a reading written with a trailing zero keeps it, or has no value. VSSTAT is "NOT DONE" or has no value, and VSREASND is "NOT ENTERED" or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/vs.csv.
prompts/sdtm-vs-diary-missed-days/brief.md
Edit10 linesFollowing CDISC SDTM standards, use the provided DIARY_DAYS, TEMPERATURE, and VACCINATION datasets to create a VS dataset with one record per subject per vaccination given per day of the temperature diary period.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, VSSEQ, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSSTAT, VSREASND, VSDTC, VSTPT, VSTPTNUM, VSTPTREF, VSRFTDTC
Read the source datasets from /app/input and save the completed dataset as /app/output/vs.csv.
R
Edit3 lineslibrary(yamaa)yamaa_spec("spec.yaml")$run()$outputPython
Edit3 linesimport yamaayamaa.spec("spec.yaml").run().outputsolutions/sdtm-vs-diary-missed-days/result.R
Edit61 lines# Reference solution for the yamaa benchmark sdtm-vs-diary-missed-days (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.suppressPackageStartupMessages({ library(dplyr) library(readr)})read_chr <- function(path) { read_csv(path, col_types = cols(.default = col_character()), na = character(), trim_ws = FALSE)}diary <- read_chr("/app/input/diary_days.csv")temp <- read_chr("/app/input/temperature.csv")vac <- read_chr("/app/input/vaccination.csv")blank_to_na <- function(x) ifelse(is.na(x) | trimws(x) == "", NA_character_, x)diary <- diary %>% mutate(VSTPTNUM = as.integer(DIARYDAY), VSTPT = DAYLABEL) %>% select(STUDYID, VSTPTNUM, VSTPT)given <- vac %>% mutate(VACDAT = blank_to_na(VACDAT)) %>% filter(!is.na(VACDAT)) %>% mutate(VACDATE = as.Date(VACDAT))temp <- temp %>% mutate(TEMPDAT = blank_to_na(TEMPDAT), TEMP = blank_to_na(TEMP), TEMPU = blank_to_na(TEMPU)) %>% filter(!is.na(TEMPDAT)) %>% select(STUDYID, USUBJID, VSDTC = TEMPDAT, VSORRES = TEMP, VSORRESU = TEMPU)vs <- given %>% inner_join(diary, by = "STUDYID", relationship = "many-to-many") %>% mutate(VSDTC = format(VACDATE + (VSTPTNUM - 1L), "%Y-%m-%d"), VSTPTREF = VISIT, VSRFTDTC = VACDAT) %>% left_join(temp, by = c("STUDYID", "USUBJID", "VSDTC")) %>% mutate( DOMAIN = "VS", VSTESTCD = "TEMP", VSTEST = "Temperature", entered = !is.na(VSORRES), VSSTAT = ifelse(entered, NA_character_, "NOT DONE"), VSREASND = ifelse(entered, NA_character_, "NOT ENTERED") ) %>% arrange(USUBJID, VACDATE, VSTPTNUM) %>% group_by(USUBJID) %>% mutate(VSSEQ = row_number()) %>% ungroup() %>% select(DOMAIN, STUDYID, USUBJID, VSSEQ, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSSTAT, VSREASND, VSDTC, VSTPT, VSTPTNUM, VSTPTREF, VSRFTDTC)dir.create("/app/output", showWarnings = FALSE)write_csv(vs, "/app/output/vs.csv", na = "")solutions/sdtm-vs-diary-missed-days/result.py
Edit73 lines# Reference solution for the yamaa benchmark sdtm-vs-diary-missed-days (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.import csvimport datetime as dtfrom pathlib import PathINPUT = Path("/app/input")OUTPUT = Path("/app/output")COLUMNS = [ "DOMAIN", "STUDYID", "USUBJID", "VSSEQ", "VSTESTCD", "VSTEST", "VSORRES", "VSORRESU", "VSSTAT", "VSREASND", "VSDTC", "VSTPT", "VSTPTNUM", "VSTPTREF", "VSRFTDTC",]def read(name): with open(INPUT / name, newline="", encoding="utf-8") as handle: return [ {k.strip(): (v or "").strip() for k, v in row.items()} for row in csv.DictReader(handle) ]def main(): days = sorted(read("diary_days.csv"), key=lambda r: int(r["DIARYDAY"])) temps = {} for row in read("temperature.csv"): temps.setdefault((row["USUBJID"], row["TEMPDAT"]), row) given = [v for v in read("vaccination.csv") if v["VACDAT"]] given.sort(key=lambda v: (v["USUBJID"], v["VACDAT"], int(v["DOSENUM"] or 0))) records = [] seq = {} for vac in given: start = dt.date.fromisoformat(vac["VACDAT"]) for day in days: num = int(day["DIARYDAY"]) date = (start + dt.timedelta(days=num - 1)).isoformat() temp = temps.get((vac["USUBJID"], date)) seq[vac["USUBJID"]] = seq.get(vac["USUBJID"], 0) + 1 records.append({ "DOMAIN": "VS", "STUDYID": vac["STUDYID"], "USUBJID": vac["USUBJID"], "VSSEQ": seq[vac["USUBJID"]], "VSTESTCD": "TEMP", "VSTEST": "Temperature", "VSORRES": temp["TEMP"] if temp else "", "VSORRESU": temp["TEMPU"] if temp else "", "VSSTAT": "" if temp else "NOT DONE", "VSREASND": "" if temp else "NOT ENTERED", "VSDTC": date, "VSTPT": day["DAYLABEL"], "VSTPTNUM": num, "VSTPTREF": vac["VISIT"], "VSRFTDTC": vac["VACDAT"], }) OUTPUT.mkdir(parents=True, exist_ok=True) with open(OUTPUT / "vs.csv", "w", newline="", encoding="utf-8") as handle: writer = csv.DictWriter(handle, fieldnames=COLUMNS) writer.writeheader() writer.writerows(records)if __name__ == "__main__": main()solutions/sdtm-vs-diary-missed-days/result.sas
Edit51 lines/* opensas reference solution for the yamaa benchmark sdtm-vs-diary-missed-days. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data vaccination; length STUDYID USUBJID VISIT $1024; infile "/app/input/vaccination.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. DOSENUM VISIT : $char1024. VACDAT : yymmdd10.; /* A vaccination with no date was not given and expects no diary. */ if not missing(VACDAT);run;data diary_days; length STUDYID DAYLABEL $1024; infile "/app/input/diary_days.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. DIARYDAY DAYLABEL : $char1024.;run;data temperature; length STUDYID USUBJID TEMP TEMPU $1024; infile "/app/input/temperature.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. TEMPDAT : yymmdd10. TEMP : $char1024. TEMPU : $char1024.;run;/* Each vaccination given with each diary day; Day 1 is the day of vaccination. The entered temperature, when there is one, is matched by subject and diary date. */proc sql; create table expected as select v.STUDYID, v.USUBJID, v.VISIT, v.VACDAT, d.DIARYDAY, d.DAYLABEL, v.VACDAT + d.DIARYDAY - 1 as DIARYDAT from vaccination as v inner join diary_days as d on v.STUDYID=d.STUDYID; create table joined as select e.*, t.TEMP, t.TEMPU from expected as e left join temperature as t on e.USUBJID=t.USUBJID and e.DIARYDAT=t.TEMPDAT;quit;proc sort data=joined; by STUDYID USUBJID VACDAT DIARYDAY; run;data result; length DOMAIN $2 VSTESTCD VSTEST VSORRES VSORRESU VSSTAT VSREASND VSDTC VSTPT VSTPTREF VSRFTDTC $1024; set joined; by STUDYID USUBJID; retain VSSEQ; if first.USUBJID then VSSEQ=0; VSSEQ+1; DOMAIN='VS'; VSTESTCD='TEMP'; VSTEST='Temperature'; VSORRES=TEMP; VSORRESU=TEMPU; VSSTAT=''; VSREASND=''; if missing(TEMP) then do; VSSTAT='NOT DONE'; VSREASND='NOT ENTERED'; end; VSDTC=put(DIARYDAT, yymmdd10.); VSTPT=DAYLABEL; VSTPTNUM=DIARYDAY; VSTPTREF=VISIT; VSRFTDTC=put(VACDAT, yymmdd10.);run;proc sql; create table final as select DOMAIN, STUDYID, USUBJID, VSSEQ, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSSTAT, VSREASND, VSDTC, VSTPT, VSTPTNUM, VSTPTREF, VSRFTDTC from result;quit;proc export data=final outfile="/app/output/vs.csv" dbms=csv replace; run;
yamaa