As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Four methods of performing a look-ahead read

From sasCommunity
Jump to: navigation, search

A question about determining whether the dates in two records are adjacent was posed to SAS-L.

As is frequently the case, the discussion quickly morphed to a related topic; in this case, how to do a look-ahead read.

Jack Hamilton suggested the use of a second SET statement on the original data set, using the data set option FIRSTOBS=2. Richard DeVenezia submitted sample data and code using the BY statement; Jack submitted sample code that doesn't use a BY statement.

Here's the code to create the sample data:

data demo;
   input k $ val @@ ;
cards;
a 11 a 12 a 13
b 21
c 31 c 32
d 41 d 42 d 43 d 44
;

Here's Jack's code:

data lookahead1 (drop=nextk);
 
   set demo end=endmain;
 
   if not endnext then 
      set demo (firstobs=2 
                keep=k val
                rename=(k=nextk val=nextval))
          end=endnext;
 
   if (k ne nextk) or endmain then 
      nextval = .;
 
run;

Here's Richard's code:

data lookahead2 (drop=i);
 
   set demo;
   by k; 
 
   if (first.k or not last.k) then
      do i = 1 to 1 + (first.k and not last.k);
         set demo(keep=val rename=(val=nextval) );
      end;
   if last.k then 
      nextval = .;
 
run;

Both methods produce the same output:

Obs    k    val    nextval
 
  1    a     11       12
  2    a     12       13
  3    a     13        .
  4    b     21        .
  5    c     31       32
  6    c     32        .
  7    d     41       42
  8    d     42       43
  9    d     43       44
 10    d     44        .

Ed Heaton later posted a method, credited to Mike Rhoads, of using MERGE for the same effect, without the need to do a special check for the last observation:

Options mergeNoBy=noWarn ;
Data lookahead1( drop=nextk ) ;
   Merge
      demo
      demo(
         firstObs=2
         rename=( k=nextK val=nextVal )
      )
   ;
   ...
Run ;
Options mergeNoBy=error ;

Howard Schreier posted generalized code which looks ahead an arbitrary number of observations:

%let lookdepth = 2;
 
data lookahead&LOOKDEPTH(drop = many count close_to_last i);
 
   do many = 1 by 1 until (last.k);
      set demo(keep=k);
      by k;
      end;
   do count = 1 to many;
      set demo;
      by k;
      close_to_last = (many - count) < &LOOKDEPTH ;
      if (first.k or not close_to_last) then
       do i = 1 to 1 + first.k * min(&LOOKDEPTH,many-1);
         set demo(keep=val rename=(val=ahead&LOOKDEPTH.val) );
         end;
      if close_to_last then do;
         ahead&LOOKDEPTH.val = .;
         end;
      output;
      end;
 
run;