SAS (Base SAS)+
*==============================================================================;
* Create the input dataset;
*==============================================================================;
data pmin;
input usubjid visitnum score;
datalines;
101 1 20
101 2 .
101 3 30
102 1 90
102 2 10
102 3 .
102 4 91
102 5 .
;
run;
*==============================================================================;
* Sort the dataset by usubjid and visitnum;
*==============================================================================;
proc sort data=pmin;
by usubjid visitnum;
run;
*==============================================================================;
* Retain previous non-missing low score;
*==============================================================================;
data pmin01;
set pmin;
by usubjid visitnum;
retain minscore;
* Store the original score;
orig_score = score;
if first.usubjid then minscore = .;
*Store minimum score and assign minscore when score is missing;
if not missing(score) then minscore = min(score,minscore);
else score=minscore;
run;- To carry the running minimum score forward within each subject, we combine
RETAINwith a conditionalmin()on each row. - After sorting by subject and visit, we reset
minscoreat the start of each subject withif first.usubjid then minscore = .;— otherwise the minimum from the previous subject would leak in. - On every non-missing row, we update
minscore = min(score, minscore). SAS treats missingminscore(the reset value) as smaller than any number, so the first non-missing score becomes the starting minimum automatically. - On rows where
scoreitself is missing, we substitute the runningminscoreintoscore— filling NAs with the running low. - We keep
orig_scoreas a snapshot of the original value so the substitutions are auditable. - After running, we check that
minscorenever increases within a subject and that filled rows show the running minimum rather than the original missing.