carpenter's complete guide to the sas(r) macro language

Upload: nishuamin

Post on 30-Oct-2015

155 views

Category:

Documents


2 download

DESCRIPTION

SAS Macros

TRANSCRIPT

/*-------------------------------------------------------------------*/

/*-------------------------------------------------------------------*/

/* Carpenter's Complete Guide to the SAS(R) Macro Language */

/* by Art Carpenter */

/* Copyright(c) 1998 by SAS Institute Inc., Cary, NC, USA */

/* SAS Publications order # 56100 */

/* ISBN 1-58025-137-4 */

/*-------------------------------------------------------------------*/

/* */

/* This material is provided "as is" by SAS Institute Inc. There */

/* are no warranties, express or implied, as to merchantability or */

/* fitness for a particular purpose regarding the materials or code */

/* contained herein. The Institute is not responsible for errors */

/* in this material as it now exists or will exist, nor does the */

/* Institute provide technical support for it. */

/* */

/*-------------------------------------------------------------------*/

/* Questions or problem reports concerning this material may be */

/* addressed to the author: */

/* */

/* SAS Institute Inc. */

/* Books by Users */

/* Attn: Art Carpenter */

/* SAS Campus Drive */

/* Cary, NC 27513 */

/* */

/* */

/* If you prefer, you can send email to: [email protected] */

/* Use this for subject field: Comments for Art Carpenter */

/* */

/*-------------------------------------------------------------------*/

Following are the programs used in the text and appendicies of the book.

Search for the appropriate code by finding the section number associated

with the program in the book. For instance to find the code used in

section 3.1.2 search for the string ***3.1.2***. The examples available

listed below.

For those macros that are named you may also search for the name of the macro.

The following examples are contained in this file:

***2.6.1***

***2.6.3***

***2.7.1***

***2.7.2***

***2.9***

***3.1.1***

***3.1.2***

***3.4***

***3.5.2***

***3.7***

***4.2.1***

***4.2.2***

***4.3.1***

***4.4***

***4.6***

***5.1.1a***

***5.1.1b***

***5.2.2***

***5.3.1***

***5.3.2***

***5.3.3***

***5.3.4***

***5.6.8***

***5.6.9***

***6.2.1a***

***6.2.1b***

***6.2.1c***

***6.2.2***

***6.3***

***6.4.1***

***6.4.2a***

***6.4.2b***

***7.1.2***

***7.2.2***

***7.2.3***

***7.3.3***

***7.4.2a***

***7.4.2b***

***8.2.4***

***8.3.2***

***9.1***

***9.2***

***9.3***

***10.1.1***

%CATCOPY

***10.1.2***

%DUMPIT

Clarence Wm. Jackson

***10.1.3***

%UPDATE

Jorn Lodahl

***10.1.4***

%CHKCOPY

***10.1.5a***

%CMBNSUBJ

***10.1.5b***

%CMBNSUBJ

***10.1.5c***

%CMBNSUBJ

***10.2.1***

%TF

David Shannon

***10.2.2***

%REPORT

Paul Kairis

NIKH Corporation

***11.1.1***

%SAS2RAW

***11.1.2***

%DELIM

Susan Haviar

***11.2.1***

%TOPPCNT

Diane Goldschmidt

***11.2.2***

%SELPCNT

***11.2.3a***

%RAND_WO

***11.2.3b***

%RAND_W

***11.3***

%EXIST

***11.4.1a**

Kim Kubasek

***11.4.1b***

Kim Kubasek

***11.4.2***

Jorn Lodahl

***11.5.1***

%OBSCNT

***11.5.2***

%TESTPRT

Jerry Kagan

Kagan Associates, Inc.

***12.2.2***

%LEFT

SAS Institute, Inc.

***12.2.3***

%CMPRES

SAS Institute, Inc.

***12.2.4***

%LOWCASE

SAS Institute, Inc.

***13.1.1***

%COUNTER

David Shannon

***13.1.2***

%INDVAR

Jorn Lodahl

***13.1.3***

%SUMS

Justina M. Flavin

STATPROBE, Inc.

***13.1.4***

%GETKEYS

Richard O. Smith

Science Explorations

***13.1.5***

%SYMCHK

***13.2***

%DBVAL

***A.2.1***

***A.2.3***

***A.3.1***

***A.4.3***

***A.5.2***

***A.5.6***

***A.5.7***

***A.6.2***

***A.6.3***

***A.6.4***

***A.7.4***

***BIOMASS***

***CLINICS***

***2.6.1***

data old;

do batch=1 to 3;

conc=2;

datadate='02jan97'd;

datatime = '09:00't;

output;

end;

format datadate mmddyy10. datatime time5.;

run;

data new;

set old;

if batch = 2 then do;

conc=2.5;

datadate="&sysdate"d;

datatime="&systime"t;

end;

run;

proc print data=new;

title1 'Drug concentration';

title2 "Mod date &sysdate";

run;

***2.6.3***

* Copy the current version of the COMBINE files

* to COMBTEMP;

proc datasets memtype=data;

copy in=combine out=combtemp;

quit;

%put SYSERR is &syserr;

***2.7.1***

%let cln = Beth;

proc sql noprint;

select count(*)

into :nobs

from clinics(where=(clinname=:"&cln"));

quit;

%put number of clinics for &cln is &nobs;

***2.7.2***

data class;

input name $ 8. grade $1.;

cards;

Billy B

Jon C

Sally A

run;

data school;

input name $ 8. gradcode $1.;

cards;

Billy Y

Frank Y

Jon N

Laura Y

Sally Y

run;

proc sql noprint;

select quote(name)

into :clnames separated by ' '

from class;

quit;

data clasgrad;

set school (where=(name in(&clnames)));

run;

proc print data=clasgrad;

title 'Class Graduate Status';

run;

***2.9***

*******************************************************;

**** The class data set, CLINICS, contains 80 ****;

**** observations and 20 variables. The following ****;

**** program will be used to complete the exercises****;

**** in this chapter. ****;

*******************************************************;

PROC PLOT DATA=CLASS.CLINICS;

PLOT EDU * DOB;

TITLE1 'YEARS OF EDUCATION COMPARED TO BIRTH DATE';

RUN;

PROC CHART DATA=CLASS.CLINICS;

VBAR WT / SUMVAR=HT TYPE=MEAN;

TITLE1 'AVERAGE HEIGHT FOR WEIGHT GROUPS';

RUN;

***3.1.1***

%LET DSN = CLINICS;

%MACRO LOOK;

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn (OBS=10);

RUN;

%MEND LOOK;

***3.1.2***

DATA invert.SPECIE;

INFILE 'SPECIES.mas';

LENGTH SPCODE $ 5 SPNAME $ 40;

INPUT SPCODE 21-25 SPNAME;

run;

%macro comment;

* Create the POSITION data set;

DATA DBMASTER.POSITION;

INFILE POS;

LENGTH POS $ 2;

INPUT POS 1-2 /*COORD 4-8*/;

FILE ERRS;

IF _ERROR_ THEN PUT '-1';

run;

%mend comment;

data new;

set big;

run;

%macro debugnew;

proc print data=new (obs=5);

title 'listing for NEW';

run;

%mend debugnew;

***3.4***

%macro pgm;

pgm;

recall;

zoom on;

%mend pgm;

***3.5.2***

option cmdmac;

%macro zpgm / cmd;

pgm;

recall;

zoom on;

%mend zpgm;

***3.7***

*******************************************************;

**** The class data set, CLINICS, contains 80 ****;

**** observations and 20 variables. The following ****;

**** program will be used to complete the exercises****;

**** in this chapter. ****;

*******************************************************;

PROC PLOT DATA=CLASS.CLINICS;

PLOT EDU * DOB;

TITLE1 'YEARS OF EDUCATION COMPARED TO BIRTH DATE';

RUN;

PROC CHART DATA=CLASS.CLINICS;

VBAR WT / SUMVAR=HT TYPE=MEAN;

TITLE1 'AVERAGE HEIGHT FOR WEIGHT GROUPS';

RUN;

***4.2.1***

%MACRO DOCHART(VAR1,VAR2);

proc chart data=ptstats;

vbar &var1 &var2;

run;

%mend dochart;

%MACRO LOOK(dsn,obs);

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn (OBS=&obs);

TITLE2 "FIRST &obs OBSERVATIONS";

RUN;

%MEND LOOK;

***4.2.2***

%MACRO SORTIT(DSN,BY1,BY2,BY3);

PROC SORT DATA=&DSN;

BY &BY1 &BY2 &BY3;

RUN;

%MEND SORTIT;

***4.3.1***

%MACRO LOOK(dsn=CLINICS,obs=);

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn (OBS=&obs);

TITLE2 "FIRST &obs OBSERVATIONS";

RUN;

%MEND LOOK;

***4.4***

%MACRO LOOK(dsn,obs=10);

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn (OBS=&obs);

TITLE2 "FIRST &obs OBSERVATIONS";

RUN;

%MEND LOOK;

***4.6***

*******************************************************;

**** The class data set, CLINICS, contains 80 ****;

**** observations and 20 variables. The following ****;

**** program will be used to complete the exercises****;

**** in this chapter. ****;

*******************************************************;

PROC PLOT DATA=CLASS.CLINICS;

PLOT EDU * DOB;

TITLE1 'YEARS OF EDUCATION COMPARED TO BIRTH DATE';

RUN;

PROC CHART DATA=CLASS.CLINICS;

VBAR WT / SUMVAR=HT TYPE=MEAN;

TITLE1 'AVERAGE HEIGHT FOR WEIGHT GROUPS';

RUN;

***5.1.1a***

%MACRO DOBOTH;

%SORTIT(CLINICS,LNAME,FNAME)

%LOOK(OBS=10)

%MEND DOBOTH;

%MACRO LOOK(dsn=CLINICS,obs=);

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn (OBS=&obs);

TITLE2 "FIRST &obs OBSERVATIONS";

RUN;

%MEND LOOK;

%MACRO SORTIT(DSN,BY1,BY2,BY3);

PROC SORT DATA=&DSN;

BY &BY1 &BY2 &BY3;

RUN;

%MEND SORTIT;

***5.1.1b***

%MACRO DOBOTH(d,o,b1,b2,b3);

%SORTIT(&d,&b1,&b2,&b3)

%LOOK(&d,&o)

%MEND DOBOTH;

%MACRO LOOK(dsn,obs);

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn (OBS=&obs);

TITLE2 "FIRST &obs OBSERVATIONS";

RUN;

%MEND LOOK;

%MACRO SORTIT(DSET,BY1,BY2,BY3);

PROC SORT DATA=&DSET;

BY &BY1 &BY2 &BY3;

RUN;

%MEND SORTIT;

***5.2.2***

%macro senrate(&num);

... code not shown ...

data senrate.rtsen#

set ratedata;

* Table 5 has sex already defined. 3 & 7 do not;

* output one obs for each sex;

%if &num=5 %then output senrate.rtsen#

%else %do;

* output the obs for each sex;

sex='F';output senrate.rtsen#

sex='M';output senrate.rtsen&num

%end;;

... code not shown ...

%mend senrate;

***5.3.1***

%MACRO DOBOTH(dsn,obs,by1,by2,by3);

%IF &BY1 ^= %THEN %DO;

PROC SORT DATA=&DSN;

BY &BY1 &BY2 &BY3;

RUN;

%END;

PROC CONTENTS DATA=&dsn;

TITLE "DATA SET &dsn";

RUN;

PROC PRINT DATA=&dsn

%IF &OBS>0 %THEN %DO;

(OBS=&obs);

TITLE2 "FIRST &obs OBSERVATIONS"

%END;

;

RUN;

%MEND DOBOTH;

***5.3.2***

%MACRO ALLYR(START,STOP);

DATA ALLYEAR;

SET

%DO YEAR = &START %TO &STOP;

YR&YEAR(IN=IN&YEAR)

%END;;

YEAR = 1900

%DO YEAR = &START %TO &STOP;

+ (IN&YEAR*&YEAR)

%END;;

RUN;

%MEND ALLYR;

***5.3.3***

%MACRO ALLYR(START,STOP);

%LET CNT = 0;

%DO %UNTIL(&YEAR >= &STOP);

%LET YEAR = %EVAL(&CNT + &START);

DATA TEMP;

SET YR&YEAR;

YEAR = 1900 + &YEAR;

RUN;

PROC APPEND BASE=ALLYEAR DATA=TEMP;

RUN;

%LET CNT = %EVAL(&CNT + 1);

%END;

%MEND ALLYR;

***5.3.4***

%MACRO ALLYR(START,STOP);

%LET CNT = 0;

%DO %WHILE(&YEAR 0 %then %do;

* DETERMINE HOW MANY DIGITS ARE NEEDED FOR EACH NUMERIC VARIABLE;

* _D STORES THE MAXIMUM NUMBER OF DIGITS NEEDED FOR EACH NUMERIC VARIABLE;

DATA M2; SET &dsn..&mem (KEEP=_NUMERIC_) END=EOF;

ARRAY _D DIGIT1 - DIGIT&NNUM;

ARRAY _N _NUMERIC_;

KEEP DIGIT1 - DIGIT&NNUM;

RETAIN DIGIT1 - DIGIT&NNUM;

IF _N_ = 1 THEN DO OVER _D; _D=1; END;

DO OVER _D;

_NUMBER = _N;

_D1 = LENGTH(LEFT(PUT(_NUMBER,BEST16.)));

_D2 = _D;

* NUMBER OF DIGITS NEEDED;

_D = MAX(_D1, _D2);

END;

IF EOF THEN OUTPUT;

RUN;

%end;

*** THIS SECTION DOES NOT WRITE DATA ONLY THE PUT STATEMENT;

*MAKE THE PUT STATEMENT AND SET IT ASIDE .;

* It will serve as documentation as well as the PUT;

DATA _NULL_; SET A1 END=EOF;

RETAIN _TOT 0 _COL 1;

FILE DDOUT NOPRINT lrecl=250;

IF _N_ = 1 THEN DO;

%if &nnum > 0 %then SET M2;;

_TOT = NPOS;

END;

%if &nnum > 0 %then %do;

ARRAY _D (NNUM) DIGIT1 - DIGIT&NNUM;

* TYPE=1 FOR NUMERIC VARS;

IF TYPE=1 THEN DO;

NNUM + 1;

DIGIT = _D;

* TAKE THE FORMATTED LENGTH INTO CONSIDERATION;

LENGTH = MAX(FORMATL, FORMATD, DIGIT);

END;

%end;

_TOT = _TOT + LENGTH + 1;

CHAR = ' ';

* SPECIAL HANDLING IS REQUIRED WHEN FORMATS ARE USED.

* CHAR IS USED TO STORE THE FORMAT;

IF FORMAT ^= ' ' | FORMATL>0 | FORMATD >0 THEN DO;

* BUILD THE FORMAT FOR THIS VARIABLE;

CHAR = TRIM(FORMAT);

IF FORMATL>0 THEN CHAR= TRIM(CHAR)||TRIM(LEFT(PUT(FORMATL,3.)));

CHAR= TRIM(CHAR)||'.';

IF FORMATD>0 THEN CHAR= TRIM(CHAR)||TRIM(LEFT(PUT(FORMATD,3.)));

END;

IF TYPE = 2 & FORMAT = ' ' THEN CHAR = '$';

* _COL IS THE STARTING COLUMN;

IF _N_ = 1 THEN _COL = 1;

IF _N_ = 1 THEN PUT '/* *** */ PUT @' _COL NAME CHAR;

ELSE PUT '/* *** */ @' _COL NAME CHAR;

_COL = _COL + LENGTH + 1;

IF EOF THEN DO;

PUT '/* *** */ ;' ;

CALL SYMPUT('LRECL',_TOT);

END;

RUN;

* Write out the flat file using the PUT statement in DDOUT;

DATA _NULL_; SET &dsn..&mem;

FILE DDOUT NOPRINT MOD lrecl=250;

%INCLUDE DDOUT;

run;

%MEND sas2raw;

****************************************************;

%SAS2RAW(sasclass,ca88air) run;

***11.1.2***

%DELIM

Susan Haviar

%delim(vitals,log)

* delim.sas

*

* Convert a SAS data set to a comma delimited flat file.;

*

* Presented at PharmaSUG April, 1997

* by Susan Haviar

*;

data vitals;

input value $10. target $8. nums err mini maxi;

cards;

Diastolic Baseline 8 64.5 59 74

Diastolic 0.25 hrs 8 66.6 57 72

Diastolic 0.50 hrs 8 62.9 51 70

Diastolic 1 hrs 8 69.5 57 88

Diastolic 2 hrs 8 69.8 53 83

run;

%macro delim(dsn,oout);

filename &oout "d:\junk\&dsn..txt";

proc contents data=&dsn

out=_temp_(keep=name npos)

noprint;

run;

proc sort data=_temp_;

by npos;

run;

data _null_;

set _temp_ end=eof;

call symput('var'||left(put(_n_,5.)),name);

if eof then call symput('total',left(put(_n_,8.)));

run;

data _null_;

file &oout noprint;

set &dsn;

put

%do i=1 %to &total;

&&var&i +(-1)','

%end;

+(-1)' ';

run;

%mend delim;

%delim(vitals,outfile)

***11.2.1***

%TOPPCNT

Diane Goldschmidt

%macro toppcnt(dsn,idvar,pcnt);

****************************************************************;

* CREATE TABLE PCNT FOR INDICATING &PCNT OF Ids *;

****************************************************************;

PROC SQL NOPRINT;

SELECT

COUNT(DISTINCT &IDVAR) *&PCNT INTO :IDPCNT

FROM

&dsn; ****