/* Appendix 1 -- COMBO  MACRO -- Updated 3 Nov 95        */

/********************/
/*   COMBO  MACRO   */
/********************/

%macro combo (n,r);
data combo;
    keep v1-v&r n r;
    array word (*) w1-w&n;
    array rr (*) r1-r&r;
    array v $8 v1-v&r;
    n = &n; r = &r;
  %do i = 1 %to &n;  w&i=&i;
  %end;
  %do i=1 %to &r;
      %if &i = 1 %then %do;
        do r&i=1to &n-(&r-&i);
        %end;
      %else %do;
        do r&i = r%eval(&i-1)+1 to &n-(&r-&i);
        %end;
      %end;
 do k=1 to &r;
   v(k)=word (rr(k));
 end;
   output;
 %do i=1 %to &r;
   end;
 %end;
run;
%mend combo;

/***********************************/
/*  CREATE GLOBAL MACRO VARIABLES  */
/***********************************/

%global n r tot m1 m2 md lxp rxp xpb;


/******************************/
/*  RANDOMIZATION TEST MACRO  */
/******************************/

%macro rmtest (dset,group,code1,code2,score);

%let n=;
%let r=;
%let tot=;
%let m1=;
%let m2=;
%let md=;
%let tot=;
%let lxp=0;
%let rxp=0;
%let xpb=0;

proc sort data=&dset;
  by &group;
run;

data &dset;
   set &dset;
   nn + 1;sumtot + &score;
run;

/* REGULAR T-TEST RESULTS */

proc ttest data=&dset;
  title "RESULTS OF";
  class &group;
  var &score;
run;


data numbers;
  set &dset;
  by &group;
  if first.&group then do;
        sumgrp=0;
        ng = 0;
    end;
    sumgrp + &score;ng + 1;
  if (last.&group and &group = &code1) then do;
        call symput('r',left(nn));        * get the number in first group;
        call symput('s1',left(sumtot));   * get sum of scores in first group;
        mn1 = sumgrp/ng;
        call symput('m1',left(mn1));
      end;
  if (last.&group and &group = &code2) then do;
        call symput('n',left(nn));        * get total number in both groups;
        call symput('tot',left(sumtot));  * get sum of scores in both groups;
        mn2 = sumgrp/ng;
        mdiff = (sumgrp)/(ng)-(sumtot-sumgrp)/(nn-ng);
        call symput('m2',left(mn2));
        call symput('md',left(mdiff));
    end;

run;

proc transpose data=&dset out=trtest;
  var &score;
run;


/* INVOKE COMBO MACRO TO GENERATE ALL POSSIBLE ARRANGEMENTS  */

%combo (&n,&r);


/* COMPUTE GROUP MEANS AND DIFFERENCE BETWEEN GROUP MEANS    */
/*   FOR EACH ARRANGEMENT                                    */

data trtest (drop=_name_ sum1 i);
  if _n_ = 1 then set trtest;
  set combo;
  array scores (*) col1-col&n;
  array v (*) v1-v&r;
  sum1 = 0; totsum = 0;
   do i = 1 to &n;
      if i le &r then sum1=sum1+scores{v{i}};
      totsum=totsum+scores{i};
   end;
   mean1 = sum1/&r;
   mean2 = (&tot-sum1)/(&n-&r);
   mdiff = mean2 - mean1;
run;

/* Save some space */

proc datasets lib=work;
  delete combo;
 run;
quit;

/* MAKE FREQUENCY DISTRIBUTION OF MEAN DIFFERENCES */ 
        
/*  There has been a slight modification to this section.       */
/*  Instead of using PROC FREQ as published, PROC SUMMARY       */
/*  is used in its place to overcome a limitation of PROC FREQ. */

proc summary data=trtest nway;
  class mdiff;
  output out=fdiff;
run;

data _null_;
  set trtest end=last;
  if last then call symput ('ntotal',_n_);
run;


/* Save some more space */


proc datasets lib=work;
  delete numbers trtest;
 run;
quit;

data fdiff(keep=mdiff _freq_ percent cumperct);
  set fdiff;
  percent=100* _freq_/ &ntotal;
  if _n_ = 1 then cumperct = percent;
    else cumperct + percent;
run;

proc print data=fdiff;
  title 'Distribution Of Difference Between Means Under Random Assignment';
  title2 "Observed Difference Between Group Means (Group 2 - Group 1) Equals &md
";
run;

title;


/* RESTRICT DISTRIBUTION TO TAILS */

data tails;
  set fdiff;
  if mdiff lt 0 then sign = -1;
   else sign = 1;
  percent = percent/100;
  if round(abs(mdiff),.001) ge round(abs(&md),.001);
run;

/*  Save a little more space */

proc datasets lib=work;
  delete fdiff;
 run;
quit;

proc sort data=tails;
  by sign;
run;

data tails;
  set tails;
  by sign;
  if first.sign then sump = percent;
     else sump+percent;
run;

data prob;
 set tails;
  by sign;
  if last.sign;
  if sign = -1 then do;
          low=sump;
          call symput('lxp',left(sump));
          end;
  if sign = 1 then do;
         high=sump;
         call symput('rxp',left(sump));
         end;
  if (sign lt 0 and low = .) then call symput ('lxp',0);
  if (sign gt 0 and high= .) then call symput ('rxp',0);
run;

data p;
  set prob end=last;
  xpb +sump;
  call symput('xpb',left(xpb));
  if last;
run;


title ' ';

/* PRINT RESULTS OF RANDOMIZATION TEST */

data _null_;
  file print;
  put  _page_;
  put  "                                   RESULTS OF";
  put  "                              RANDOMIZATION TEST";
  put  ' ';
  put  "Observed Difference Between Group Means (Group 2 - Group 1) Equals &md";
  put  ' ';
  put  "                    Tail Probabilities Under Randomization:";
  put  "                    P1: p <= -|&md| = &lxp";
  put  "                    P2: p >= +|&md| = &rxp";
  put  "                    p3:  Two-tail    p = &xpb";
  put  " ";
run;

/* Clean up work space */

proc datasets library=work;
  delete tails prob p;
run;
quit;


%mend rmtest;