Language macro du SAS

Transcription

Language macro du SAS
Langage Macro de SAS
L'éditeur macro de SAS fonctionne comme un éditeur de texte qui produit des programmes que le SAS
exécute. Il nous donne une façon de programmer avec des procédures de SAS.
Par exemple, on peut faire des boucles DO à l'intérieur d'une étape DATA. Avec des macros, on peut
avoir des boucles qui incluent des étapes DATA et des PROC.
Commandes et variables macro
Pour signaler au SAS qu'une commande ou une variable doit être traitée par l'editeur macro d'abord, on
ajoute le préfixe % aux commandes macro et le préfixe & aux variables macro. Par exemple, %LET
est une commande macro, &nbd est un nom macro.
Considerez le programme suivant :
libname c 'c:\donnees' ;
proc contents data=c.dossier1 ;
title1 'Contenu de dossier1' ;
proc print data=c.dossier1 ;
title1 'Listage de dossier1 ' ;
run ;
Ce programme lit une banque de données permanente de SAS, c.dossier1, et liste de l'information
sur ses variables et leurs valeurs. Le nom c.dossier1 paraît quatre fois dans le programme.
Le programme suivant qui emploie l'éditeur macro a besoin de seulement une mention du nom de la
banque de données et produit la même sortie.
libname c 'c:\donnees' ;
%LET nbd = c.dossier1 ;
proc contents data=&nbd ;
title1 "Contenu de &nbd" ;
proc print data=&nbd ;
title1 "Listage de &nbd" ;
run ;
La commande macro %LET définie une variable macro nbd avec la valeur "c.dossier1". Chaque
fois que &nbd paraît dans le programme, l'éditeur macro remplace cette valeur par c.dossier1
avant de laisser le SAS traiter le programme. (N.B. Il n'était pas nécessaire de mettre & devant nbd
dans la ligne %LET nbd = c.dossier1. Dés que le SAS voit la commande %LET il sait que la
ligne en question doit être traitée par l'éditeur macro).
On peut définir plusieurs variables macro dans un même programme. Considerez le programme
suivant :
libname c 'c:\donnees' ;
%LET nbd = c.dossier1 ;
%LET catlst = sexe race insur ;
%LET contlst = age poids taille ;
proc contents data=&nbd ;
title1 "Contenu de &nbd" ;
proc print data=&nbd ;
title1 "Listage de &nbd" ;
proc freq data=&nbd ;
tables &catlst ;
proc means data=&nbd ;
var &contlst ;
run ;
Programmes macro
On peut prendre un programme de SAS et le convertir en programme macro. De cette façon, la
prochaine fois qu'on cherche à faire la même analyse mais avec une banque de données différentes, on
pourrait employer le programme macro au lieu de tout reécrire le programme SAS.
Pour signaler le début du programme macro, on emploie la commande %MACRO; la fin est indiquée par
la commande %MEND. Par exemple, considerez ce programme macro qui fait l'analyse du dernier
programme :
%MACRO check ;
proc contents data=&nbd ;
title1 "Contenu de &nbd" ;
proc print data=&nbd ;
title1 "Listage de &nbd" ;
proc freq data=&nbd ;
tables &catlst ;
proc means data=&nbd ;
var &contlst ;
run ;
%MEND ;
Le programme au complet qui défini le macro et fait l'analyse de deux banque de données différentes
est
libname c 'c:\donnees' ;
%MACRO check ;
proc contents data=&nbd ;
title1 "Contenu de &nbd" ;
proc print data=&nbd ;
title1 "Listage de &nbd" ;
proc freq data=&nbd ;
tables &catlst ;
proc means data=&nbd ;
var &contlst ;
run ;
%MEND ;
%LET nbd = c.dossier1 ;
%LET catlst = sexe race insur ;
%LET contlst = age poids taille ;
%check
%LET nbd = c.dossier2 ;
%LET catlst = sexe race classe ;
%LET contlst = age cigaret ;
%check
Boucles DO dans un macro
%DO ___ %TO ___ %END ;
%DO %WHILE___ %END ;
%DO %UNTIL___ %END ;
Considerez les lignes de SAS suivantes qui combinent quatre banques de données.
DATA tous ;
SET fichier1 fichier2 fichier3 fichier4 ;
run ;
Le macro suivant fait la même chose.
%MACRO combine ;
DATA tous ;
SET
%DO i=1%TO 4 ;
fichier&i
%END ;
run ;
%MEND ;
%COMBINE
run ;
Pour appeler le macro, on met %COMBINE dans la bonne place dans notre programme. (Si vous
voulez voir la sortie de l'éditeur macro avant qu'elle soit envoyée au SAS, il suffit de mettre la
commande OPTIONS MPRINT; dans votre programme. Le journal affichera la sortie.)
Commandes macro plus avancées
%EVAL
Permettre d'évaluer la valeur numérique d'une variable macro. Par exemple, si k est l'indice d'une
boucle macro, la commande
%LET k=%EVAL(&k +1) ;
ajoute un à la valeur de k.
Macros avec arguments
On peut donner la valeur des variables macro quand on appelle un macro. Considérez cette
modification au macro combine qui nous permet d'indiquer le nombre de banques de données à
combiner :
%MACRO combine( num ) ;
DATA tous ;
SET
%DO i=1%TO &num ;
fichier&i
%END ;
run ;
%MEND ;
%combine(4)
Règle pour programmer un macro
1. Ecrire le programme SAS qui fait une analyse.
2. Traduire le programme en macro d'une façon itérative. A chaque étape on essaie de rendre le macro
de plus en plus général.
Par exemple, l'étape DATA suivante définie une banque de données avec 5 variables réponses, v1à v5
et deux variables indépendentes, ind1 et ind2 :
DATA xxx ;
INPUT v1-v5 ind1 ind2 ;
CARDS;
1 0 1 1 0 34 23
0 0 1 0 1 22 32
1 1
0 1
0 1
1 1
0 0
1 1
0 1
1 1
;
RUN
1
0
0
0
0
0
0
0
0
1
1
0
1
0
1
0
0
1
1
0
1
0
1
0
12
56
26
46
57
22
44
41
10
90
80
45
53
77
45
72
;
Pour faire une régression logistique avec v1 comme variable dépendante, on ajoute les commandes
PROC LOGISITIC DATA = xxx DESCENDING ;
MODEL v1 = ind1 ind2 ;
RUN ;
Pour faire l'analyse avec les variables dépendantes v2 à v5, on repète l'analyse avec v2 en place de v1
dans la commande MODEL, avec v3 dans la place de v1 dans la commande MODEL, etc. (N.B. Il n'est
pas nécessaire de maîtriser la régression logistique pour comprendre la logique des différentes étapes
de la conversion en macro d'un programme de SAS.)
On traduira ces trois lignes en macro :
OPTIONS MPRINT MLOGIC ;
%MACRO monlogit(num);
%DO i = 1 %TO &num ;
TITLE "la variable dépendante est v&i" ;
PROC LOGISTIC DATA=xxx DESCENDING ;
MODEL v&i = ind1 ind2 ;
RUN ;
%END ;
%MEND ;
%monlogit(5)
Les options MPRINT et MLOGIC produisent de l'information dans le journal qui peut nous aider à
déboguer notre macro.
Notre objectif en écrivant un macro est de développer un outil très général qu'on peut employer pour
analyser beaucoup de banques de données différentes. A présent, notre macro monlogit exige que les
variables dépendantes soient numérotées v1, v2, v3, etc. La modification suivante nous permet
d'analyser des banques de données où les noms des variables dépendantes peuvent être arbitraires.
%macro monlogit1(toutes_deps);
%let k=1;
%let dep = %scan(&toutes_deps, &k);
%do %while("&dep" NE "");
title "La variable dépendante est &dep";
proc logistic data=xxx descending;
model &dep = ind1 ind2;
run;
%let k = %eval(&k + 1);
%let dep = %scan(&toutes_deps, &k);
%end;
%mend;
%monlogit1(v1 v2 v3)
La variable macro %toutes_deps contient une liste de noms de variables dépendantes, séparés par
des espaces (« v1 v2 v3 » est un exemple d'une telle liste).
L'éditeur macro ne sait pas combien de variables sont dans %toutes_dep. Quand &k = 1, la ligne
%let dep = %scan(&toutes_deps, &k);
lit la première valeur dans la liste &toutes_deps et donne cette valeur à la variable dep (par
exemple, v1 est la première valeur de la liste v1 v2 v3). On fait la régression logistique avec cette
variable dépendante. Ensuite, on ajoute 1 à k et on lit la prochaine valeur dans %toutes_dep avec
les lignes
%let k = %eval(&k + 1);
%let dep = %scan(&toutes_deps, &k);
La boucle %DO %UNTIL qui suit vérifie que la liste n'est pas exhaustée (Si on a lu toutes les variables
dans la liste, la valeur de dep serait vide, indiquée par "".
On peut sortir des valeurs calculées par un macro. Le macro suivant calcule des valeurs estimées des
paramètres de la régression logistique. Essayer de suivre sa logique.
%macro monlogit1(toutes_deps, outest);
%let k=1;
%let dep = %scan(&toutes_deps, &k);
%do %while("&dep" NE "");
title "La variable dépendante est &dep";
proc logistic data=xxx des outest=_est&k;
model &dep = ind1 ind2;
run;
%let k = %eval(&k + 1);
%let dep = %scan(&toutes_deps, &k);
%end;
%if "&outest" NE "" %then
%do;
data &outest;
set
%do i = 1 %to &k - 1;
_est&i
%end;
;
run;
%let k = %eval(&k - 1);
proc datasets;
delete _est1 - _est&k;
run;
%end;
%else
%do;
%pas de banques données;
%end;
%mend;
%monlogit1(v1 v2 v3)
%monlogit1(v1 v2 v3, a)
proc print data = a;
var intercept ind1 ind2;
run;

Documents pareils