/* trimset.sas D. Brockman 070730 remove leading and trailing missing obs. */
* tested 070730 ;
%macro trimset(iset,oset,vlist);
/*
* iset = input set
* oset = output set
* vlist = list of selected vars separated by spaces.
*
* trimset returns in global macro var greturn the number of obs in oset.
*
* trimset deletes from the dataset any leading or trailing observations
* for which all the vars in vlist have missing values. trimset doesn't
* remove the all-missing obs if there is a preceding observation with
* some of these values not missing and if there is a subsequent observation
* with some of these values not missing.
*
* Take care to assure an appropriate sort order of the input data set.
*
* Lore: Inspired by a data set that, through intended calculations,
* surprisingly turned out to have many initial observations
* missing for variables of interest, though uselessly present in the data set.
*
*/
%global greturn ;
%let dsid=%sysfunc(open(&iset));
%let nobs=%sysfunc(attrn(&dsid,nobs));
%let rc=%sysfunc(close(&dsid));
%let fkeep=%eval(&nobs+1); * init first record to keep;
%let Lkeep=0; * init first record to keep;
* count the vars in our list ;
%let nv=0; * init count;
%do %while(%scan(&vlist,%eval(&nv+1)) ne ) ; * loop the vars ;
%let nv=%eval(&nv+1); * incr count ;
%end ; * end loop the vars ;
%if (&nobs gt 0 ) %then %do ; * if at least one obs in iset ;
data _null_ ;
set &iset ;
retain fkeepL4L LkeepL4L; * dont lose values found ;
array varsL4L[&nv] &vlist ; * set array on our var list ;
if (_N_=1) then do ; * only on first iteration ;
fkeepL4L=&fkeep ; * number of first observation to keep ;
LkeepL4L=&Lkeep ; * number of last observation to keep ;
end ;
missL4L=1 ; * assume all missing ;
do iL4L=1 to &nv ; * loop the var list ;
missL4L=missing(varsL4L[iL4L]) ; * is it missing? ;
if (not missL4L) then leave; * we found a value ;
end; * end loop the var list ;
if ( (not missL4L) and (fkeepL4L>_N_) ) then fkeepL4L=_N_ ; * first ?;
if ( (not missL4L) and (LkeepL4L<_N_) ) then LkeepL4L=_N_ ; * Last ?;
call symput('fkeep',fkeepL4L) ; * number of first some-not-missing obs;
call symput('Lkeep',LkeepL4L) ; * number of Last some-not-missing obs;
run;
%end; * end if nobs > 0 ;
data &oset ; * create output set;
set &iset (firstobs=&fkeep obs=&Lkeep) ;
run;
%let greturn=%eval(&Lkeep-&fkeep+1); * number of obs in oset;
%mend trimset ;