From: Subject: Date: Fri, 16 Mar 2012 12:15:47 +1100 MIME-Version: 1.0 Content-Type: text/html; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable Content-Location: http://members.iinet.net.au/~brucebra/code/utility/ABSJack.sas X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6109
%*************************      ABSJack    =
*******************************;
%************      Based loosely on the SAS 'Jack' macro    =
**************;=20
%*    Requires a previously defined macro called analyse, which has      =
*;
%*    parameters data, results, weight and print.                        =
*;
%*    See the accompanying program ABSJackExample.sas for usage.         =
*;
%*    To improve performance, do as much processing and data subsetting  =
*;
%*    prior to the analyse macro, and make the &data file as small =
as    *;
%*    possible. HOWEVER, any processing that requires the use of the     =
*;=20
%*    weight must take place within the analyse macro.                   =
*;
%*    The output file has one row per combination of &id and =
&stat       *;
%*    variables with information on the estimate, its variance,          =
*;
%*    std error and RSE.                                                 =
*;
%*    The program creates a number of temporary files in the Work =
folder.*;
%*    These are all prefixed with ABSJack_                               =
*;
%*                                                                       =
*;
%*    Updated January 2011 to handle procedures that do and dont have   =
*;
%*    variable labels.                                                   =
*;
%*                                                                       =
*;
%*    If you use this macro, please cite it as                           =
*;
%*    Bradbury, Bruce (2011), "ABSJack", SAS computer code, v1.1.        =
*;
%*    [http://www.sprc.unsw.edu.au/tatlib/ABSJack.sas]                   =
*;
%*                                                                       =
*;
%*    Please report problems and improvements to                         =
*;
%*    b.bradbury@unsw.edu.au                                             =
*;
%************************************************************************=
*;
* Utility macro used later;
%macro vexist (dsn=3D, vname=3D) ;=20
%* Returns 1 if the variable exists in the dataset, zero otherwise.;
   %local exist dsid varcnt rc ;=20
   %let exist =3D 0 ;=20
   %if not %sysfunc (exist (&dsn)) %then %do ;=20
      %put ERROR: Data set %upcase (&dsn) does not exist. ;=20
      %goto mexit ;=20
   %end ;=20
   %let dsid  =3D %sysfunc (open (&dsn)) ;=20
   %do varcnt =3D 1 %to %sysfunc (attrn (&dsid, nvars)) ;=20
      %if %upcase (%sysfunc (varname (&dsid, &varcnt))) =3D =
%upcase (&vname) %then %do ;=20
         %let exist =3D 1 ;=20
         %goto leave ;=20
      %end ;=20
   %end ;=20
   %leave:=20
   %let rc =3D %sysfunc (close (&dsid)) ;=20
   &exist=20
   %mexit:=20
%mend vexist ;=20
%macro ABSJack(     =20
   data=3D,            /* input data */
   stat=3D_numeric_,   /* variables to have variances calculated (all =
numeric vars if not specified) */
   id=3D,              /* id variables that uniquely identify output =
rows.
                        These will usually be the class variables in the =
output (if they exist) */
   w0=3D,              /* main weight variable */
   prefix=3D,          /* prefix for replicate weight vars */
   nrep=3D30,          /* number of replicates */
   twodigit=3D0,        /* Replicate weight vars are assumed to take the =
form=20
                        &prefix1 - &prefix&nrep if =
twodigit=3D0 or
                        &prefix01 - &prefix&nrep if =
twodigit=3D1   */
   output=3DABSJack_output,  /* output file with std errors etc */
   print=3Dnoprint     /* use print=3Dprint if you want the results of =
each iteration printed */
   );
%*** call the analyse macro to calculate the actual values;
%analyse(data=3D&data,results=3DABSJack_Actual,weight=3D&w0,print=
=3D&print);
%if &syserr>4 %then %goto exit;
* add in extra vars to the output file;
data ABSJack_Actual (compress=3Dno);=20
  set ABSJack_Actual;
  _replicate_ =3D 0;
  label _replicate_=3D"Replicate"; /* needed to ensure a label column in =
the transposed file */
run;
* create an empty file to hold all the results;
data ABSJack_Dist (compress=3Dno); set ABSJack_Actual; delete; run;
%*** call the analyse macro using each replicate weight in turn;
%do _replicate_ =3D 1 %to &nrep;
  %if &twodigit %then %do;
    %if %length(&_replicate_) =3D 1 %then %let repvar =3D =
&prefix.0&_replicate_;
    %else %let repvar =3D &prefix.&_replicate_;
  %end;
  %else %let repvar =3D &prefix.&_replicate_;
  %put **** Using weight variable &repvar ****;
  =
%analyse(data=3D&data,results=3DABSJack_Rep,weight=3D&repvar,prin=
t=3D&print);
  %if &syserr>4 %then %goto exit;
  * add in extra vars to the output file;
  data ABSJack_Rep (compress=3Dno);
    set ABSJack_Rep;
    _replicate_ =3D &_replicate_;
    label _replicate_=3D"Replicate"; /* needed to ensure a label col in =
the transposed file */
  run;
  %if &syserr>4 %then %goto exit;
  proc append data=3DABSJack_Rep base=3DABSJack_Dist;run;
  %if &syserr>4 %then %goto exit;
%end;
%***** calculate jackknife standard errors;
%* put actual results in a vector form;
proc transpose data=3DABSJack_Actual out=3DABSJack_Actual_Vec =
(compress=3Dno) prefix=3Dvalue;
  var &stat;
  by &id;
run;
%if &syserr>4 %then %goto exit;
%* Depending on the procedure used in the analyse macro, the =
ABSJack_Actual file
   might or might not have variables with labels. If they do, we should =
sort and merge by
   this to ensure uniqueness. This next bit of code tests whether the =
transposed
   file has a _label_ variable and puts this string into a macro =
variable if it does;
%if %vexist(dsn=3DABSJack_Actual_Vec,vname=3D_label_) %then %let label =
=3D _label_;
%else %let label =3D ;
proc sort data=3DABSJack_Actual_Vec;by &id _name_ &label;run;
%* put replicate results in a vector form;
proc sort data=3DABSJack_Dist;by &id _replicate_;
proc transpose data=3DABSJack_Dist out=3DABSJack_Dist_Vec =
(compress=3Dno) prefix=3Ddistvalue;
  var &stat;
  by &id _replicate_;
run;
%if &syserr>4 %then %goto exit;
proc sort data=3DABSJack_Dist_Vec;by &id  _name_  _replicate_ =
&label;run;
%* merge actual and replicates and calculate variation;
data ABSJack_Dev (compress=3Dno);
  merge ABSJack_Actual_Vec ABSJack_Dist_Vec;
  by &id _name_ &label ;
  Dev =3D ((&nrep-1)/&nrep)*(distvalue1 - value1)**2;
run;
proc means data=3DABSJack_Dev noprint;
  by &id _name_ &label;
  output out=3D&Output (compress=3Dno) sum(dev)=3Dvariance =
mean(value1)=3Dvalue;
run;
data &Output (compress=3Dno);
  set &Output;
  StdError =3D sqrt(variance);
  if value^=3D0 then RSE =3D 100*stderror/value;
  t =3D value/stderror;
  run;
%exit:;
%************************************************************************=
****************;
%mend ABSJack;