You could create an array RANK_HIST analogous to the DIAG_HIST array.
But you would still have to change the logic of the loop. Instead of leaving the loop with the first non-zero DIAG_HIST you have to maintain another variable, say D_MIN, which is the value of D corresponding to the minimum RANK_HIST for non-zero DIAG_HIST.
D_MIN starts out as missing. As you go over each range (i.e. the offset D goes from start-of-range to end-of-range), whenever you hit a non-zero DIAG_HIST, then if D_MIN is missing, set it to D. But if D_MIN is not missing, compare the RANK_HIST for D to the same for D_MIN, and update D_MIN accordingly.
At the end of each range, if D_MIN is not missing, no more ranges are checked. And finally if D_MIN is not missing, assign a value to NEW_DIAG.
Something like this (totally untested):
new_diag =coalesce(diag_hist{date},diag);
array strt {3} _temporary_ (1,3,6);
array finish {3} _temporary_ (2,5,9);
d_min=.;
if new_diag^=0 then do r=1 to 3 until (d_min^=.);
do sign=-1,1 until (d_min^=.);
do d = sign*strt{r} to sign*finish{r} by sign;
if diag_hist{date+d}^=0 then do;
if d_min=. then d_min=d; else
if rank_hist{date+d} < rank_hist{date+d_min} then d_min=d;
end;
end;
end;
end;
if d_min^=. then new_diag=diag_hist{date+d_min};
Note the first inner loop ("do sign=-1,1 …") provides a way to set up this sequence of 6 ranges:
do d=-1 to -2 by -1
do d=1 to 2 by 1
do d=-3 to -5 by -1
do d=3 to 5 by 1
do d=-6 to -9 by -1
do d=6 to 9
... View more