Showing posts with label macro. Show all posts
Showing posts with label macro. Show all posts

21.8.09

Macro Variable Resolution Using Multiple Ampersands

Prepared by Meena R S (meena@kreara.com)


The SAS macro consists of two basic parts: macros and macro variables. The names of macro variables are prefixed with an ampersand (&) while the names of macros are prefixed with percent sign (%). Prior to the execution of the SAS code the macro variables are resolved. The resolved values are then substituted back into the code.


The macro variable references that have been described with one ampersand preceding the macro variable name are direct reference to a macro variable. In indirect referencing, more than one ampersand precedes a macro variable reference. The macro processor follows specific rules in resolving references with multiple ampersands.


The rules that the macro processor uses to resolve macro variable reference that contain multiple ampersands follow

  • Macro variable references are resolved from left to right
  • Two ampersands (&&) resolve to one ampersand (&)
  • Multiple leading ampersands cause the macro processor to rescan the reference until no more ampersands can be resolved.


Consider the example below.


Options symbolgen;

%let section4 =operating system;

%let n=4;

%put &&section&n;


For the above code, on the first pass the two ampersands are resolved to one and &n is resolved to 4, yielding &section4. On the second pass the macro variable reference &section4 resolves to operating system.


The following figure shows the process of resolving the macro variable reference in the program.





%let a =freight;

%let b=passenger;

%let c=special;

%let code=a;

%put &code;

%put &&code;

%put &&&code;


The following demonstrates how the macro variables with multiple ampersands are resolved.



6.3.09

The Bootstrap Method

Prepared by Meena R S

Bootstrap method is a way of simulating results for a larger number of samples based on the given sample. The bootstrap method is used to quantify the uncertainty in any parameter estimate (e.g., mean, variance, percentile value, etc.). All bootstrap methods involve generating hypothetical samples from the original sample. Each hypothetical sample is called a Bootstrap Sample.

Bootstrap method has the following assumptions

1. The sample taken should be a valid representative of the population

2. Bootstrap method takes sampling with replacement from the sample. Each sub sampling is independent and identical distribution (i.i.d.). In other words, it assumes that the sub samples come from the same distribution of the population, but each sample is drawn independently from the other samples.

The bootstrap works by computing the desired statistic for a sub sample of the data set. The sub sampling is done with replacement and the size of the sample is equal to the size of the original sample. The desired statistic is calculated for each sub sample. The collection of these statistics is used as an estimate of the sampling distribution.

Example 1: The following example represents the length of 3 different petals 10 trees of the same type. This program estimates the uncertainty parameters mean and standard deviation

data petals;
input petal1 petal2 petal3;
cards;
1.21 1.31 1.53
2.13 2.21 3.17
1.59 1.70 1.56
1.45 1.23 1.21
1.41 1.96 1.24
1.04 1.8 1.58
1.03 1.05 2.1
1.4 1.25 1.26
1.56 1.26 1.34
1.82 1.24 1.56
;
run;

* This macro is used to generate 10 bootstrap samples of the above data;

%macro bootsamp(data,boot, b);
data &boot;
do isample=1 to &b;
do i = 1 to nobs;
pt = round(ranuni(0) * nobs) ;
set &data nobs = nobs point=pt; *point options is used to create samples in any order;
output;
end;
end;
stop;
run;
%mend;

%bootsamp(petals, boot, 10); *Generating 10 bootstrap samples;

*Calculating the parameters mean and standard deviation for each subsample and appending them to obtain the final sample dataset;

%macro sample(j=, n=);
%do i=&j %to &n;
data petals1;
set boot;
where isample=&i;
run;

proc means data=petals1 ;
var petal1 petal2 petal3 ;
output out = petals_&i mean = mean std = std n =n;
run;

proc append base=final data=petals_&i force;
run;
%end;
%mend;

%sample (j=1, n=10);

proc means data=final mean std ;
var mean std;
output out = means_ mean = mean std = std n =n;
run;

Output is shown below


Use of ampersands and semicolons in SAS macros

Prepared by Jose Abraham


Single, double and triple ampersands

Multiple ampersands can be used to allow the value of a macro variable to become another macro variable reference. The macro variable reference will be rescanned until the macro variable is resolved.

The following demonstrates how macro variables with multiple ampersands are resolved. There are
4 macro variables

Macro variable :Value
A : CATCH
B : STUMP
C : RUN
HIT : A

Resolving a macro variable:

&VARNAME references a macro variable. The rule is that the scanner reads from left to right.

1. If we put one ampersand i.e., ‘&HIT’ then the macro variable hit resolves to ‘A’.

2. If we put two ampersands then the two ampersands resolve to one and scanner continues. i.e., ‘&&HIT’
On the first scan - ‘&&’ resolves to ‘&’ and ‘HIT’ held as token.
On the second scan – ‘&HIT’ resolves to ‘A’.

3. If we put three ampersands i.e., ‘&&&HIT’
On the first scan -‘&&’ resolves to & and the remaining &HIT resolves to ‘A’ and the it results ‘&A’
On the second scan –‘&A’ resolves to ‘CATCH’



Single and double semi colons
When creating macros for programming, sometimes we would like to generate a dynamic SAS statement within a macro %DO loop. For example if we want to run a print procedure inside a macro and refer to a set of macro variables within the VAR statement.

proc print;
var
%do i = 1 %to &max;
&&var&i
%end;;
run;

Consider a simple program containing this %DO loop in a macro

data one;
input A $ B C D E;
datalines;
a 12 16 18 20
;
run;

%let var1=A;
%let var2=B;
%let var3=C;
%let var4=D;
%let var5=E;
%let max=4;
%let indt=one;

%macro prnt;
proc print data=&indt.;
var
%do i = 1 %to &max.;
&&var&i
%end;;
run;
%mend;

%prnt;

In this program, there are two consecutive semicolons used after the %end statement which is not common in a simple SAS program. Here the first semicolon closes the %END and the second semicolon closes the VAR statement. And if we run this macro it will generate the following SAS statements

proc print data=one;
var a b c d;
run;

and it produces the result

10.10.08

Execute a set of files in SAS.
Prepared by Rupesh R

There are situations where prior to running a SAS Editor(s) one may be required to run a list of files (SAS or non SAS). Our objective is how to call them in a single statement.

We need to run a set of SAS files prior to a SAS code. The usual scenario is to execute them one by one. But it is possible to access a set of files or members from this storage location by a single statement as follows.

Using filename statement we assign the fileref storage in an aggregate location.

filename storage “An- Aggregate –storage- location”;

Several files or members from this storage location can be accessed by listing them in parentheses after the fileref in a single %INCLUDE statement
%inc storage (Monthly, Quarterly); Non SAS files can also be accessed using quotation marks around the complete filename listed inside the parentheses. %inc storage ("file-1.txt","file-2.dat","file-3.cat"); Auto call SAS macros and Formats When the SAS editors contain user defined macros the above %inc statement does not work. In this situation we use sasautos option. Usually the formats and macros will be in separate folders. In those situations they can be called as follows. Libname project “project-path”;Libname formlib “format –path”;Libname mymacros “macro-path”; options fmtsearch=(formlib project) sasautos=( mymacros) mautosource ;
The fmtsearch option searches the formats in the files or libraries in the following order

1. Work.formats
2. formlib.formats
3. project.formats

Sasautos option invokes the macros in the file reference storage.

The auto call facility is usually used when all user-defined macros are stored in a standard location and they are not compiled until they are actually needed.
But when we get formats and macros in the same folder it is better to use the following statement.Options fmtsearch=( storage project) sasautos=( storage ) mautosource ; Here even though library work is not specified the fmtsearch option will search for the formats in the work library by default as mentioned earlier.The formats can also be called without using fmtsearch option if we know the name of SAS file which contains all the formats for the particular study. We can access the formats using a single %include statement.

%inc storage (formats);

Here the SAS editor formats contain all the formats for the study.

26.5.08

Understanding the %pageXof Y macro

Compiled by Rupesh R

The following macro needs to be applied for the purpose of presenting page numbers in Page X of Y format within the body of the document.

When calling the macro, the proc report code should be quoted by %nrstr as explained in step 1.a below. To avoid clutter of code, here the proc report code is created as a macro. This proc report code should contain a ‘compute before_page_’ block as described in the step 5 below.

%macro pageXofY (report= /* proc report code, quoted by %nrstr */ /*1.a*/
, dummy=dummy /* name of the dummy output file */
);
%global page pages len; /* 1.b*/


/-- first run --*/
%let page = 0;
%let len = 8; /* 1.c*/
filename _dummy &dummy.; /* 1.d*/
proc printto print = _dummy; run; /*1.e*/
%unquote (&report.) ;/* 1.f*/
proc printto; run;/*1.g*/
filename _dummy clear; /*1.h*/

%*-- second run --*;
%let pages = &page.; /*1.i*/
%let page = 0;/*1.j*/
%let len = %eval(%length(&pages.) * 2 + 4); /* 1.k*/
%unquote(&report.);/*1.l*/
%mend pageXofY;

Explanation of Macro
Step 1 (1.a): Using %nrstr function we mask the special characters and mnemonics .Here we mask & and % symbols in the proc report code.

Step 2 (1.b): Initialize three global macro variables
§ The variable ‘page’ returns the current page number
§ The variable ‘pages’ returns the total number of pages
§ The variable ‘len’ returns the expected length of the string ‘_XofY’ (2.c) .

Step 3 (1.c): The initial values of macro variables ‘page’ and ‘len’ are assigned as 0 and 8 respectively.

Step 4 (1.d): A dummy file path is defined for the output of proc printto

Step 5 (1.e): PRINTTO procedure is used for printing the output in the specified dummy file (_dummy).

Step 6 (1.f): The proc report code created for generating the output is executed using %unquote function in this step.

%UNQUOTE is to restore normal tokenization of a value whose tokenization was altered by a previous macro quoting function. %UNQUOTE takes effect during macro execution. If the value is not unmasked before it reaches the SAS compiler, the DATA step does not compile correctly and it produces error messages.

1) Execute the entire report procedure and generate an output to the specified file path “&dummy.”

2) In report procedure we should include the following set of statements.

compute before/after _page_;
call execute('%let page = %eval(&page. + 1);'); /* 2.a*/
length _XofY $&len.; /* 2.b. */
_XofY = symget('page') ' of ' symget('pages');/*2.c*/
line 'page ' _XofY $&len..; /* 2.d. */
endcomp;
3) Before/After each page of reporting the variable ‘page’ is calculated and so when we exit from this procedure the macro variable ‘page’ has the value of total number of pages. (i.e. The initial value of ‘page’ is ‘0’ when it comes to the first page of file then it becomes ‘1’ and so on, see step (2.a))
4) We get the total pages of report in variable ‘page’.Here the variable “pages” is not initialized. So symget (‘pages’) will return nothing
Step 7 (1.g): Exit the printto procedure and SAS reset the file path to the output window (by default).

Step 8 (1.h): Clear the dummy file.

Step 9 (1.i): Assign the current value of variable ‘page’ to the macro variable ‘pages’. i.e. we assign the total number of pages to the variable ‘pages’

Step 10 (1.j): Reset the variable ‘page’ to ‘0’.

Step 11 (1.k): Calculate the approximate length of the variable ‘_XofY’ based on current value of ‘pages’.

Step 12 (1.l): Re-execute the report procedure for getting the output as per the requirement.
1) Execute the entire report procedure and generate output in the specified path given in the ods rtf file statement.
2) This time the compute block call the ‘page’ value as the current page and ‘pages’ as the total number of pages. So we will get the page number as Page X of Y form.
The following example illustrates the above macro.Here we get page X of Y on the top of each page.

data one;
do var = 1 to 100;
output;
end;
run;

%Macro Report;
proc report data=one nowd;
column var;
define var / display;
compute before _page_;/*2.a*/
call execute('%let page = %eval(&page. + 1);'); /* 2.b*/
length _XofY $&len.; /* 2.c. */
_XofY = symget('page') ' of ' symget('pages');/*2.d*/
line 'page ' _XofY $&len..; /* 2.e. */
endcomp;
run;
%Mend Report;

/* example usage */

options linesize=64 nonumber nodate;
%pageXofY(report=%nrstr(%Report));

15.4.08

Extracting Engine and Path name of the code
Compiled by Prajitha Nair




The input parameter in the macro will be the name of the SAS file whose path is to be determined.

%macro PathbyName(progName);

%global fullPath fullPath1 engine;
%if %index(%upcase(&progName),.SAS) eq 0 %then
%let progName=&progName..sas;

proc sql noprint;
select xpath into :fullPath
from dictionary.extfiles where
index(upcase(xpath),"%upcase(&progName) " ) gt 0 ;
select setting into :engine from sashelp.voption
where optname="ENGINE";
quit;

%let engine = %trim(&engine);
%put engine = &engine;
%let fullpath = %trim(&fullPath);

%put fullpath = &fullPath;

%mend PathbyName;

Accessing the current working directory where the file containing the SAS code is stored


Compiled by Prajitha Nair


Let the SAS editor containing the code be KR-PH-XXX-SAS-Init.sas and it is stored in a folder named SAS Programs_Final.


The following %let statements assigns the folder and editor names to macro variables pgmfld and pgm respectively.


%let pgmfld = SAS Programs_Final; /*Folder in which SAS code is stored*/
%let pgm= KR-PH-XXX-SAS-Init.sas; /*Name of the program editor*/


The following macro is then used to extract the path of the editor from sashelp.vextfl and determine the path of the folder as “dir1” and of the editor as “dir2”.


%macro filePath;
%global fpath maxRef;

proc sql noprint;
select xpath into :fPath
from sashelp.vextfl where xpath ? "&pgm";
quit;


%let fpath = %trim(&fpath);
%put &fpath;
%global dir1 dir2 pgm1 pgmfld1;
%let pgm1 =%trim(&pgm);
%let pgmfld1= %trim(&pgmfld);


data _null_;
x=length("&fpath")-length("&pgm1");
y=length("&fpath")-length("&pgm1")-length("&pgmfld1")-1;
call symput("dir2" ,trim(substr("&fpath",1,x)));
call symput("dir1" ,trim(substr("&fpath",1,y)));
run;


%mend filePath;


This macro helps in determining the path of the code and enables the code to be executed in any computer provided the SAS code is saved within a folder and the naming conventions are followed as above.

11.10.07

Transpose macro
Compiled by Ajish K Mani

%macro trans(dsn=, outdsn=, vartran=, idtran=, bytran=, copytran=);
proc transpose data=&dsn out=&outdsn let;
var &vartran;
by &bytran;

%if &copytran ne %then %do;
copy ©tran;
%end;

%if &idtran ne %then %do;
id &idtran;
%end;
run;
%mend trans;

data input
input patno 1 sex $ 3 visit 5 weight 7-8 height 10-12;
datalines;
1 m 1 80 150
2 f 1 65 160
3 f 1 70 165
4 f 1 60 170
5 m 1 68 168
;
run;

proc sort data=input out=output;
by patno;
run;


%trans (dsn=output, outdsn=transpose(rename=(col1=Result)), vartran=weight height, bytran=patno);

data transpose;
set transpose;
label _name_ ="Parameter" ;
rename _name_=Parameter;
run;

25.7.07

LOCF

In clinical trials, data are often collected over a period of time from participating patients. In many situations, however, analyses are only based on data from the last time point (the end of the study) or change from the baseline to the last time point. It is often the case that patients drop out before the completion of the study.

So the question arises on how to perform analysis of the last observations, which are defined as observations from the last time point for patients who completed the study and the last observations prior to the dropout for patients who did not complete the study.

An analysis based only on data from patients who completed the study is called a completers analysis. Although a completers analysis is sufficient in some situations, it is often more desirable to perform an all randomized subjects analysis.

The analysis based on all randomized subjects is usually referred to as an intention-to-treat (ITT) analysis. Regulatory agencies generally consider the ITT analysis as the primary analysis for evaluation of efficacy and safety in clinical trials with informative dropout.

When the dropout is informative, the target populations of a completers analysis and an ITT analysis are different. Suppose that the population of patients under certain treatment is stratified according to the time of the last observations; then the target population of a completers analysis is only the subpopulation of patients who completed the study under different treatments while the target populations of an ITT analysis include all the subpopulations under different treatments.

For the last observation carry-forward (LOCF) analysis based on ITT population, the last observations are carried forward to the last time point for patients who dropped out. The LOCF analysis treats the carried-forward data as observed data at the last time point. Therefore when the dropout is informative, the LOCF analysis may introduce biases to the statistical inference, which has been speculated upon by the Food and Drug Administration (FDA) it is still unknown whether or not the LOCF test is asymptotically correct

Here is a macro that might help you with LOCF