I have multiple date variables (date1, date2, ..., date8) that I am taking the earliest of them (min (of date1 - date8)) and using for censoring in a time-to-event analysis.
Some dates could be the same; others may be missing.
I'd like to output which date(s) were the minimum, thus used for censoring and output VNAME. Is there a way, by arrays maybe to output a one column that tells which of these dates equaled the minimum?
for example:
date1 date2 date3 date4 date5 ... minDate
1/1/12 . 5/7/13 . . date1
. 6/5/12 . 6/5/12 . date2/date4
and so on ...
Thanks
Here are two ways to do it. The first only picks one minimum; the second is a bit more work but will pick multiple.
WHICHN() function tells you which argument after the first has the value of the first argument (only tells you the first one, though). For both solutions, VNAME() tells you the variable name of the variable in the array.
data have;
input
date1 date2 date3 date4 date5;
informat date1-date5 MMDDYY8.;
format date1-date5 DATE9.;
datalines;
1/1/12 . 5/7/13 . .
. 6/5/12 . 6/5/12 .
;;;;
run;
data want;
set have;
array dates date1-date5;
format minDateVal $200.;
minDate = whichn(min(of dates
if (1 le minDate lt dim(dates)) then
minDateVal = vname(dates[mindate]);
end;
put minDateVal=;
run;
data want;
set have;
array dates date1-date5;
format minDateVal $200.;
do _t = 1 to dim(dates);
if dates[_t] = min(of dates
minDateVal = catx(',',minDateVal,vname(dates[_t]));
end;
run;
have a look at the WHICHN() function
data foo;
format date1-date8 yymmdd10.;
array date[8];
do i = 1 to 1000;
call missing( of date
do j = 1 to 8;
if ranuni(4350982)<2/5 then date
end;
output;
end;
drop i j;
run;
data bar;
array date[8];
length minDate $ 200;
format min yymmdd10.;
set foo;
min=min(of date
if min > 0 then do;
_n_ = whichn( min , of date
do while( _n_ > 0 );
minDate=catx( '/' , minDate , vname( date[_n_] ) );
call missing( date[_n_] );
_n_ = whichn( min , of date
end;
end;
run;
Here are two ways to do it. The first only picks one minimum; the second is a bit more work but will pick multiple.
WHICHN() function tells you which argument after the first has the value of the first argument (only tells you the first one, though). For both solutions, VNAME() tells you the variable name of the variable in the array.
data have;
input
date1 date2 date3 date4 date5;
informat date1-date5 MMDDYY8.;
format date1-date5 DATE9.;
datalines;
1/1/12 . 5/7/13 . .
. 6/5/12 . 6/5/12 .
;;;;
run;
data want;
set have;
array dates date1-date5;
format minDateVal $200.;
minDate = whichn(min(of dates
if (1 le minDate lt dim(dates)) then
minDateVal = vname(dates[mindate]);
end;
put minDateVal=;
run;
data want;
set have;
array dates date1-date5;
format minDateVal $200.;
do _t = 1 to dim(dates);
if dates[_t] = min(of dates
minDateVal = catx(',',minDateVal,vname(dates[_t]));
end;
run;
Thanks guys; the below has worked fine for me...
data have;
set have;
array _dates date1..... date8;
array _dateName $ datename1... datename8;
do over _dates;
if _dates= MinDate then _dateName=VNAME(_dates);
end;
minimumDateNames=catx('/', of datename1-datename8 );
run;
My pet peeve of the day: a couple of your colleagues gave you good solutions, but you opted to post your own variant and declare it the correct answer. Okay, a poster CAN come up with the best answer to their own question, but your "correct" answer doesn't even do what you asked for
Hey Arther; sorry for your disappointment! snoopy's second part does what I wanted too, in addition to mine . To cheer up a bit, I changed the "correct" answer.
I think that looping over the array of dates is probably clearer when you want to find ALL of the examples that match the minimum. The extra array of variable names is not needed since you can accumulate the names right into the target variable as you detect them.
data have;
informat date1-date8 date9.;
format date1-date8 date9.;
input date1-date8;
cards;
01jan2013 02jan2013 01jan2013 . . . . .
run;
data want;
set have;
array _dates date1 - date8;
length mindate 8 minimumDateNames $200 ;
mindate = min(of _dates(*));
format mindate date9.;
do over _dates;
if _dates= MinDate then
minimumDateNames=catx('/',minimumDateNames,VNAME(_dates))
;
end;
put (_all_) (=/);
run;
date1=01JAN2013
date2=02JAN2013
date3=01JAN2013
date4=.
date5=.
date6=.
date7=.
date8=.
mindate=01JAN2013
minimumDateNames=date1/date3
Makes perfect sense. Thanks for clarification Tom!
Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.
Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.