h1

Répéter une action sur plusieurs variables avec le langage macro

août 13, 2008

Sous SAS, deux possibilités sont envisageables pour répéter une action sur plusieurs variables. Dans le cas d’un data step, la syntaxe de l’ARRAY est tout à fait appropriée. Dans d’autres cas, le langage macro peut s’avérer plus pertinent. Voici donc une présentation de l’approche via le langage macro.

1. L’exemple

Pour illustrer le propos, le programme aura pour but de définir un PROC REPORT contenant toutes les variables du data set SASHELP.CLASS. Si on connaît le nom des variables, la syntaxe se résume de la manière suivante.

proc report data=sashelp.class;
   columns name age sex weight height;
   define name   / display;
   define age    / display;
   define sex    / display;
   define weight / display;
   define height / display;
run;

Mais si on ne connaît pas le nom des variables par avance, il faut automatiser la tâche.

2. Remplacer le nom des variables par des macros variables

Dans l’exemple suivant, le nom de chaque variable est sauvegardé dans une macro variable. Ces macros variables ont une structure particulière :

un préfixe commun + un nombre

%let class1 = name;
%let class2 = age;
%let class3 = sex;
%let class4 = weight;
%let class5 = height;

proc report data=sashelp.class;
   columns name age sex weight height;
   define &class1. / display;
   define &class2. / display;
   define &class3. / display;
   define &class4. / display;
   define &class5. / display;
run;

3. Répéter l’instruction DEFINE grâce à une boucle

Grâce à cette structure particulière, une boucle peut être envisagée. L’instruction DEFINE est alors répétée autant de fois qu’il y a de variables. La boucle est définie par une macro variable « I » qui prend des valeurs allant de 1 à 5. La partie nombre de la macro variable est donc remplacée par la valeur de la macro variable « I ».

NOTE : Pour résoudre la macro variable lors de la première boucle, SAS effectue deux lectures. A la première lecture, les deux perluètes (ampersand) && se transforment en un seul ; &i. se transforme en 1. On a donc &CLASS1. A la deuxième lecture, SAS résout la macro variable &CLASS1. comme précédemment.

%macro test;
   proc report data=sashelp.class;
   columns name age sex weight height;
   %do i=1 %to 5
      define &&class&i. / display;
   %end;
   run;
%mend test;
%test;

4. Créer les macros variables de manière automatique

Pour créer les macros variables automatiquement, il faut agir en deux étapes.

  1. Enregistrer chacune des noms de variables du data set choisi dans PROC REPORT (SASHELP.CLASS) dans un nouveau data set (LST_VAR) et plus particulière dans une variable (NAME).
  2. Associer un numéro à chaque nom de variable (compteur) et convertir l’information en macro variable (CALL SYMPUT).

proc sql;
   create table lst_var as
      select name
      from dictionary.columns
      where upcase(libname)=‘SASHELP’ and
            upcase(memname)=‘CLASS’;
quit;

data _null_;
   set lst_var;
   cnt+1;
   call symput (cats(‘CLASS’,put(cnt,best.)),name);
run;

5. Compter le nombre de variables de manière automatique

Si le nombre de variable dans le data set n’est pas connu à l’avance, il faut le retrouver. Cette information est ensuite sauvegardée dans une macro variable, disons MAX_VAR, et remplacera notre nombre 5. L’article « 3 méthodes pour construire des macro variables sans macro » vous donnera plus de précisions concernant la création d’une macro variable.

Obtenir rapidement le nombre de variables dans un data set : Un moyen pour trouver le nombre de variables est de faire appel au dictionnaire de SAS intitulé TABLES.

proc sql noprint;
   select nvar into : max_var
   from dictionary.tables
   where upcase(libname)=‘SASHELP’ and
         upcase(memname)=‘CLASS’;
quit;

Plus de flexibilité sur la liste des variables concernées : Un autre moyen pour compter le nombre de variables est d’agir en deux étapes.

  • Enregistrer dans un variable d’un nouveau data set chacune des noms de variables de SASHELP.CLASS.
  • Compter le nombre d’observations dans ce data set. Vous pouvez vous reporter à l’article « Combien d’observations dans mon data set » pour plus de précisions sur les différentes alternatives.

Dans notre exemple, il s’agit de créer le data set LST_VAR pour la première étape. Le code de la section 4 est tout à fait suffisant pour cela. Ensuite, CALL SYMPUTX peut servir à sauvegarder l’information dans une macro variable.

data _null_ ;
   call symputx(‘max_var’,_N_-1);
   set lst_var;
run;

Pourquoi vous ai-je proposé cette alternative ?  Ici, toutes les variables sont sélectionnées. Mais si seulement quelques une sont choisies, seule la seconde alternative marche. Voici quelques sous-sélections possibles.

  • Sélectionner toutes les variables numériques,
  • Sélectionner toutes les variables finissant pas _X,
  • etc.

En résumé : En résumé, le code se décompose en 2 étapes : créer les macros variables et utiliser ces macros variables pour définir une boucle.

*1. Créer les macros variables CLASS1 à CLASS5, MAX_VAR.;

*1.1 Créer le data set LST_VAR servant de fichier de référence.;

proc sql;
   create table lst_var as
      select name
      from dictionary.columns
      where upcase(libname)=‘SASHELP’ and
            upcase(memname)=‘CLASS’;
quit;

*1.2 Créer les macro variables CLASS1-CLASS5 en se basant sur le data set LST_VAR créé précédemment.;

data _null_;
   set lst_var;
   cnt+1;
   call symput (cats(‘CLASS’,put(cnt,best.)),name);
run;

*1.3 Créer la macro variable VAR_MAX en se basant sur le data set LST_VAR créé précédemment.;

data _null_ ;
   call symputx(‘max_var’,_N_-1);
   set lst_var;
run;

*2. Reporting : appeler les différentes macro variables pour créer la boucle autour de l’instruction DEFINE.;

%macro test;
proc report data=sashelp.class;
   columns name age sex weight height;
   %do i=1 %to &max_var.;
      define &&class&i. / display;
   %end;
run;
%mend test;
%test;

5 commentaires

  1. Bonjour,

    Dans la macro %test, est-il vraiment nécessaire de mettre 3 & ?
    Deux semblent suffire.

    SD


  2. Bonsoir,

    Autant pour moi. Deux en effet suffisent. J’ai fais la mise à jour. Cela m’apprendra à écrire des posts à 11h du soir ;)

    Véronique


  3. Bonjour,

    Merci pour cet article, c’est exactement ce que je recherche.

    Est-il possible de remplacer la ligne suivante par une boucle %do afin que le proc report soit entièrement automatique à partir de la liste des macro variables ?
    columns name age sex weight height;

    Julien V.


  4. Il me suffisait d’essayer pour avoir la réponse à ma question :

    proc report data=sashelp.class;
    columns %do i=1 %to &max_var.; &&class&i. %end;;

    %do i=1 %to &max_var.;
    define &&class&i. / display;
    %end;
    run;


  5. J’ai une question concernant une boucle svp.

    Je voudrai pouvoir générer une table dans laquelle certaines variables sont crées (idm et icard) en repérant les éléments de chaine de caractères sur l’ensemble des 65 variables initiés dans la boucle. Pour l’instant, il me génère 65 tableaux et par conséquent le traitement qui en résulte est celui réalisé sur la 65 e table pourtant je veux qu’il le fasse pour les 65 variables (autrement sur les 65 tables).
    lignes de code:

    %macro code;
    %do i=1 %to 62;
    proc sql;
    create table amphi.data09dw1 as
    select id_sejour,
    case when substr(comor&i,1,4)=’I252′ then 1
    when substr(comor&i,1,3) in (‘I21’, ‘I22’)then 1
    else 0 end as idm,
    case when substr(comor&i,1,4) in (‘I099′,’I110′,’I130′,’I132′,’I255′,’I420’, ‘I425′,’I426′,’I427′,’I428′,’I429′,’P290’) then 1
    when substr(comor&i,1,3)in (‘I43′,’I50’) then 1
    else 0 end as icard
    from amphi.data09dw;
    quit;
    %end; %mend;

    %code;

    je vous remercie par avance pour votre aide!



Répondre

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l'aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

%d blogueurs aiment cette page :