BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Altal
Calcite | Level 5

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

1 ACCEPTED SOLUTION

Accepted Solutions
snoopy369
Barite | Level 11

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

  • ),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

  • ) then
  •     minDateVal = catx(',',minDateVal,vname(dates[_t]));

    end;

    run;

    View solution in original post

    8 REPLIES 8
    Peter_C
    Rhodochrosite | Level 12

    have a look at the WHICHN() function

    FriedEgg
    SAS Employee

    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='01JAN2013'd + floor( (1+today()-'01JAN2013'd)*ranuni(567890) );

    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;

    snoopy369
    Barite | Level 11

    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

  • ),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

  • ) then
  •     minDateVal = catx(',',minDateVal,vname(dates[_t]));

    end;

    run;

    Altal
    Calcite | Level 5

    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;

    art297
    Opal | Level 21

    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 Smiley Sad

    Altal
    Calcite | Level 5

    Hey Arther; sorry for your disappointment! snoopy's second part does what I wanted too, in addition to mine Smiley Wink. To cheer up a bit, I changed the "correct" answer.

    Tom
    Super User Tom
    Super User

    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

    Altal
    Calcite | Level 5

    Makes perfect sense. Thanks for clarification Tom!

    sas-innovate-2024.png

    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.

     

    Register now!

    How to Concatenate Values

    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.

    Click image to register for webinarClick image to register for webinar

    Classroom Training Available!

    Select SAS Training centers are offering in-person courses. View upcoming courses for:

    View all other training opportunities.

    Discussion stats
    • 8 replies
    • 1090 views
    • 6 likes
    • 6 in conversation