In alcune occasioni ci troviamo nella condizione di dover eseguire del codice più volte durante il programma oppure una parte di programma farebbe al caso nostro anche in altre occasioni. Ad esempio vogliamo scrivere un programma che prima di eseguire una regressione esegua la "miglior trasformazione" box-cox sulla variabile di risposta. Le macro rispondono a questo tipo di esigenze: la caratteristica principale delle macro è la flessibilità nei cambiamenti del codice e la creazione di codice modulare.
Tipicamente una macro accetta parametri in entrata, e produce dei risultati. Una volta creata e mandata in esecuzione la macro,il macro-processore di Sas processa e "produce" codice Sas che verrà eseguito.
Per distingurli dai comandi Sas. i comani macro seguono le seguenti regole:
Qui vedremo i concetti fondamentali delle macro.
Creare macro è abbastanza semplice e si fa con due comandi.
%macro nomemacro(parametri);
...comandi....
%mend nomemacro
La macro viene richiamata dal programma sas tramite il comando:
%nomemacro(parametri)
Assegnare una variabile macro è altrettanto semplice e si fa con il comando:
%let variabilemacro=valore;
Di seguito vediamo un esempio in cui creiamo una macro che manda in output dati "filtrati" secondo i paramatri passati alla macro:
%macro filtra(sc=,
v=);
/*inizia la macro*/
proc sort data=salari
out=filtrati;
/*filtro i dati in base ai parametri creando un nuovo dataset*/
by
&v;
where scuola=≻
proc print
data=filtrati;
/*stampo i dati filtrati*/
title "dati ordinati (per voto) della scuola &sc
";
%mend
filtra;
/*termina la
macro*/
data
salari;
/*importo i dati*/
infile "H:\datiprova\salari.dat"
firstobs=2;
input voto sal scuola
$;
run;
%filtra(sc="LA",v=voto);
/*richiamo la
macro*/
%filtra(sc="E",v=voto);
/*richiamo la macro con parametri
diversi*
Il data-set importato contiene informazioni su salari, voto di laurea e tipo di laurea. La macro filtra il data-set selezionando il tipo di scuola (parametro sc) e la variabile su cui ordinare; che in questo caso è il voto ma poteva essere anche il salario.
Una delle potenzialità delle macro sta nel fatto che si può sciegliere dinamicamente quale pezzo di codice (interno alla macro) mandare in esecuzione. Questo si ottiene grazie ai comandi macro:
%if condizione
%then azione;
oppure
%if condizione %then
%do;
%else
azione ...comandi...
%end %end
Riprendiamo l'esempio di prima, solo che stavolta passiamo due variabili di ordinamento: il salario e il voto. Voglio ottenere due report diversi a seconda di qual'e la variabile la variabile di ordinamento passata.
%macro filtra(sc=,
v=);
/*inizia la macro*/
%if &v=voto %then
%do;
/*controllo se la variabile di ordinamento è il voto*/
proc sort data=salari
out=filtrati;
by &v;
where
scuola=≻
proc print
data=filtrati;
title "dati ordinati (per voto) della scuola "
≻
%end;
/*fine primo controllo*%
%if &v=sal %then
%do;;
/*controllo se la variabile di ordinamento è il salario*/
proc sort data=salari
out=filtrati;
by &v;
where
scuola=≻
proc print
data=filtrati;
title "dati ordinati (per stipendio) della scuola "
≻
%end;
/*fine secondo controllo*/
%mend filtra;
/*termina la
macro*/
data salari;
/*importo i dati*/
infile "H:\datiprova\salari.dat"
firstobs=2;
input voto sal scuola
$;
run;
%filtra(sc="LA",v=voto);
/*richiamo la macro e passo come variabile di ordinamento il
voto*/
%filtra(sc="LA",v=sal);
/*richiamo la macro e passo come variabile di ordinamento il salario*/
Come si vede la macro produce output diversi a seconda di quali sono i parametri passati
In alcune occasioni non sappiamo a priori quali variabili macro creare, ma la decisione deve essere presa in run time ossia in maniera dinamica. Sas permette ciò grazie al comando:
call symput("nomevariabile",valore);
In questo modo sas crea una variabile macro di nome nomevariabile a le associa il valore valore. Riprendiamo ancora l'esempio di prima. Stavolta come filtro vogliamo il voto + basso del tipo di scuola che passiamo come parametro
%macro filtra(sc=,
v=);
/*inizia la macro*/
proc sort data=salari
out=filtrati;
/*filtro i dati in base ai parametri creando un nuovo dataset*/
by
&v;
where scuola=≻
data _null_ ;set
filtrati;
/*considero il data-set filtrato*/
if _N_ = 1
then call symput
("piccolo",voto); /*creo una variabile macro di
nome piccolo a cui do il valore della prima osservazione del data-set
filtrato(il minore)*/
proc print data=filtrati;
where
&v=&piccolo;
title "il voto + piccolo è &piccolo per la
scuola " ≻
%mend filtra;
/*termina la
macro*/
data salari;
/*importo i dati*/
infile "H:\datiprova\salari.dat"
firstobs=2;
input voto sal scuola
$;
run;
%filtra(sc="BUS",v=voto);
%filtra(sc="LA",v=voto);
Come vediamo è stata creata una variabile dinamicamente. In questo caso le abbiamo attribuito il primo valore del dataset ordinato (il minore).