DATA Step, Macro, Functions and more

array q

Reply
Occasional Contributor
Posts: 19

array q

data a;
input subject $ visit $ labdt $ cd1 $ cd2 $ cd3 $ cd4 $;
cards;
101 1 15JUN15 17JUN15 18JUN15 29JUN15 31AUG15
101 2 20JUN15 17JUN15 18JUN15 29JUN15 31AUG15
101 3 01AUG15 17JUN15 18JUN15 29JUN15 31AUG15
102 1 19JUN15 17JUN15 28JUN15 29JUN15 31SEP15
102 1 28JUN15 17JUN15 28JUN15 29JUN15 31SEP15
;
run;

data b;
set a;
by subject visit;
array vis[*] cd1-cd4;
do i = 1 to dim(vis);

if input(labdt,date9.) le input(vis[i],date9.) then chk=vlabel(vis[i]);
else if input(labdt,date9.) < input(vis[i],date9.) and input(labdt,date9.) ge input((vis[i+1]),date9.)
then chk=vlabel(vis[i+1]);
end;

run;

 

why isnt chk assgined properly. basically i want to check if labdt falls between which cdx variables?

 

thk

Super User
Posts: 23,950

Re: array q

You should consider a binary search method instead of looping through the entire array as well...though it's likely the easiest approach.

 

You don't have a LEAVE, which you should, once your condition is met, otherwise, it will check each i regardless.

 

 

 

 

Occasional Contributor
Posts: 19

Re: array q

thx LEAVE worked ..

 

thx again

Super User
Posts: 6,901

Re: array q

If that's all you did, you will get error messages on some days, and not on other days.  It depends on what is in the data.  If you get as far as I=4, then what do you think will happen when your code references vis[I+1] ??

Super User
Posts: 13,886

Re: array q

[ Edited ]

Do you get the same invalid data notes that I do when I run your code? 31SEP15 is not a valid date.

 

Is there any reason the dates weren't created as date values with the appropriate informat when created? I find that having actual date values usually simplifies code a lot.

 

You might show what your are expecting to get for a result.

I think that you may have the direction of your comparisons backwards in the ELSE if, your loop is going to attempt to execute one too many times for most cases. If you want to stop as soon as you find the boundary value/variable the below shows an example.

data a;
input subject $ visit $ labdt $ cd1 $ cd2 $ cd3 $ cd4 $;
cards;
101 1 15JUN15 17JUN15 18JUN15 29JUN15 31AUG15
101 2 20JUN15 17JUN15 18JUN15 29JUN15 31AUG15
101 3 01AUG15 17JUN15 18JUN15 29JUN15 31AUG15
102 1 19JUN15 17JUN15 28JUN15 29JUN15 30SEP15
102 1 28JUN15 17JUN15 28JUN15 29JUN15 30SEP15
;
run;

data b;
   set a;
   by subject visit;
   array vis[*] cd1-cd4;
   do i = 1 to (dim(vis) -1);

      if input(labdt,date7.) le input(vis[i],date7.) then do; 
         chk=vlabel(vis[i]);
         leave;
      end;
      else if input(labdt,date7.) ge input(vis[i],date7.) and input(labdt,date7.) le input((vis[i+1]),date7.)
      then do;
         chk=vlabel(vis[i+1]);
         leave;
      end;
   end;

run;

 This assumes that the cd1 to cd4 are sorted in ascending order.  

Occasional Contributor
Posts: 19

Re: array q

i could have used full dates instead of date7.   i believe the date will fall under one category only so do you think backward will produce different result than the current one?

Super User
Posts: 13,886

Re: array q


eric2 wrote:

i could have used full dates instead of date7.   i believe the date will fall under one category only so do you think backward will produce different result than the current one?


If I understand your question, likely the choice of date7 vs date9 shouldn't matter. I just try  to match the informat to actual range of characters/digits I have as there are some times that a longer informat than the value may cause problems.

 

If the original dates had been read using date7 informat then the comparison code would be much cleaner and easier to follow.

Plus if you need to do anything else, such as the difference between the test date and the boundary date you would have to convert the values again to use intck function.

Esteemed Advisor
Posts: 5,614

Re: array q

If CD1 <= CD2 <= CD3 <= CD4 then you must stop the loop as soon as labdt <= CDi

 

data b;
set a;
array vis[*] cd1-cd4;
do i = 1 to dim(vis);

    if input(labdt,date9.) le input(vis[i],date9.) then do;
        chk=vlabel(vis[i]);
        leave;
        end;
    end;

run;

 

 

PG
Ask a Question
Discussion stats
  • 7 replies
  • 136 views
  • 0 likes
  • 5 in conversation