tags:

views:

360

answers:

4

Is there a way to check how many observations are in a SAS data set at runtime OR to detect when you've reached the last observation in a DATA step?

I can't seem to find anything on the web for this seemingly simple problem. Thanks!

+3  A: 

Find the number of observations in a SAS data set:

proc sql noprint;
  select count(*) into: nobs
  from sashelp.class
  ;
quit;

data _null_;
  put "&nobs";
run;

The SQL portion counts the number of observaions, and stores the number in a macro variable called "nobs". The data step puts the number for display, but you can use the macro variable like any other.

Performing a certain action when the last observation is processed:

data _null_;
  set sashelp.class end=eof;
  if eof then do;
     put name= _n_=;
  end;
run;

The "end" option to the "set" statement defines a variable (here "eof" for end-of-file) that is set to 1 when the last observation is processed. You can then test the value of the variable, and perform actions when its value is 1. For more info, see the documentation for the "set" statement.

Martin Bøgelund
Thanks for this - having that macro variable option is definitely handy to know :)
chucknelson
+5  A: 

The nobs= option to a set statement can give you the number of observations. When the data step is compiled, the header portion of the input datasets are scanned, so you don't even have to execute the set statement in order to get the number of observations. For instance, the following reports 2 as expected:

/* a test data set with two observations and no vars */
data two;
  output;
  output;
run;

data _null_;
  if 0 then set two nobs=nobs;
  put nobs=;
run;
/* on log
nobs=2
*/

The end= option sets a flag when the last observation (for the set statement) is read in.

A SAS data set, however, can be a SAS data file or a SAS view. In the case of the latter, the number of observations may not be known either at compile time or at execution time.

data subclass/view=subclass;
  set sashelp.class;
  where sex = symget("sex");
run;

%let sex=F;
data girls;
  set subclass end=end nobs=nobs;
  put name= nobs= end=;
run;
/* on log
Name=Alice nobs=9.0071993E15 end=0
Name=Barbara nobs=9.0071993E15 end=0
Name=Carol nobs=9.0071993E15 end=0
Name=Jane nobs=9.0071993E15 end=0
Name=Janet nobs=9.0071993E15 end=0
Name=Joyce nobs=9.0071993E15 end=0
Name=Judy nobs=9.0071993E15 end=0
Name=Louise nobs=9.0071993E15 end=0
Name=Mary nobs=9.0071993E15 end=1
*/
Chang Chung
Thanks for the multitude of options in here, I ended up going w/ the END option for now. Great to see a whole variety of ways to do this :)
chucknelson
+2  A: 

You can also use %sysfunc(attrn( dataset, nlobs)) though it is limited to SAS data sets (i.e. not data views). Credit for the macro to this SUGI paper, which also give great information regarding good macro design.

You can get all sorts of other character and numeric information on a SAS data set.

See the documentation on attrn and attrc.

%macro numobs (data=&syslast ) ;
/* --------------------------------------------
Return number of obs as a function
--------------------------------------------
*/
%local dsid nobs rc;
%let data = &data ; /* force evaluation of &SYSLAST */
%let dsid=%sysfunc(open(&data));
%if &dsid > 0 %then
%do ;
   %let nobs=%sysfunc(attrn(&dsid,nlobs));
   %let rc=%sysfunc(close(&dsid));
%end ;
%else
   %let nobs = -1 ;
&nobs
%mend numobs;
cmjohns
This method gets my vote..
Bazil
+1  A: 

data hold;
.. set input_data end=last;
.
.
.
.. if last then do;
.
.
.
.. end;
run;