Annonce

Bienvenue sur le site support des ouvrages :
SAS - Introduction au décisionnel : méthode et maîtrise du langage
(1ère édition - épuisée)
SAS - Introduction pratique : du data management au reporting (2ème édition - épuisée)
SAS - Introduction au décisionnel : du data management au reporting (3ème édition - épuisée (hélas...))

la réponse à la question "mais où trouver la 3ème édition ?" est précisée ici


Retrouvez dans ce tiré à part, la préface écrite par Mouloud Dey, Directeur Business solutions et marchés émergents, SAS France,
l’introduction générale ainsi que le plan complet de l’ouvrage

#1 24-05-2018 13:27:29

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Mon sujet de langage macro sous SAS

ça vous dirait de vous amuser avec le sujet d'examen de mon cours de langage macro sous SAS que j'ai proposé à mes étudiants du M1 ESA ?

alors, c'est parti !


Je viens de me découvrir une brusque passion pour le commerce extérieur de la France. Je suis donc allé sur le site de l’INSEE pour récupérer des séries d’exportations et d’importations vers les 25 pays européens vers lesquels la France commerce le plus et j’ai construit une jolie table SAS (CEXT).

Voici un extrait de cette table :

http://www.sas-sr.com/img/su_ma1.png

Les 25 séries « E » mesurent des exportations (en millions d’euros), les 25 séries « I » mesurent des importations.

Bon… pas très facile de savoir à quel pays ces chiffres se rapportent… heureusement, on dispose d’une seconde table (PAYS)

http://www.sas-sr.com/img/su_ma2.png

Que faire avec ces données… un graphique !

Voici le programme que j’ai rédigé pour avoir une idée de l’état de nos échanges commerciaux avec l’Allemagne (les tables CEXT et PAYS ont été placés dans la bibliothèque de travail au préalable).

Code:

data cext2;
   set cext;
   solde=E1-I1;
   pctco=(e1+i1)/(sum(of e:)+sum(of i:));
run;

Au cours de cette première étape DATA, je calcule un solde, différence entre les exportations et les importations. Je voulais aussi savoir la part que représente notre commerce avec l’Allemagne parmi les échanges que nous avons avec nos 25 principaux partenaires européens. Cette part est calculée tous les mois mais c’est en fait la donnée la plus récente qui va m’intéresser : 0.24154 en mars 2018, soit 24.2%.

Code:

proc means data=cext2 noprint;
   ways 1 ;
   class date;
   format date year4.;
   var e1 i1 solde;
   output out=cext3 sum= exp imp solde;
run;

je ne veux pas représenter des séries mensuelles (trop de points, on ne verrait pas grand-chose) mais des séries annuelles. Le PROC MEANS présenté ici, va me calculer ces séries annuelles dans une table de résultats appelée CEXT3.

Code:

data cext3 ;
   set cext3;
   exp=12*exp/_freq_;
   imp=12*imp/_freq_;
   solde=12*solde/_freq_;
run;

Il faut quand même que je corrige mes données : en effet, pour 2018, je n’ai que 3 mois de données et par conséquent, cette année n’est pas directement comparable aux autres années (qui, elles, contiennent 12 mois…). Aussi, j’effectue une petite correction pour permettre la comparaison.

Code:

title "Allemagne : Exportations, Importations et solde commercial";
Title2 "En mars 2018, ce pays représentait 24.2% de nos échanges";
title3 "avec nos 25 principaux partenaires commerciaux européens";
Footnote "Attention, pour 2018, on ne dispose en réalité que de 3 mois de données";
Footnote2 "pour rendre comparables les chiffres, on multiplie les données de 2018 par 12/3";
proc sgplot data=cext3 noautolegend;
   refline 0 / axis=y;
   series x=date y=exp / lineattrs=(thickness=2pt color=blue)  
                         curvelabel="Exportations" ;
   series x=date y=imp / lineattrs=(thickness=2pt color=red) 
                         curvelabel="Importations" ;
   series x=date y=solde / lineattrs=(thickness=2pt) 
                           curvelabel="Solde";
   xaxis display=(nolabel);
   yaxis display=(nolabel);
run;

et j’obtiens ceci :

http://www.sas-sr.com/img/su_ma3.png

Votre objectif est de créer deux macro-programmes :
1-    Le premier (15 points en tout) n’admet qu’un paramètre : le nom d’un pays. Vous devez obtenir le graphique caractérisant les échanges que la France a avec ce pays.
a.    Si en paramètre de votre macro, vous mettez ALLEMAGNE, Allemagne, ou allemagne, le graphique doit être produit. (2 points)
b.    Si le pays n’existe pas ou qu’il est mal orthographié (Grece au lieu de Grèce), un message doit apparaître dans le journal indiquant ceci :
Le pays que vous avez demandé n’est pas dans la liste des pays possibles (ou alors, vous l’avez mal orthographié…). Voici la liste des pays pour lesquels le macro-programme peut produire un graphique »
        Et bien entendu, il doit apparaître une liste des pays possibles. (3 points)
c.    Je reprends ici le graphique en encadrant les éléments qui vont devoir d’adapter automatiquement à votre demande.
http://www.sas-sr.com/img/su_ma4.png

Si j’actualise la table en ajoutant les données d’avril 2018, les titres et pied de page doivent automatiquement s’adapter. Bien entendu, lorsque la donnée la plus récente est relative à un mois de décembre, puisqu’il n’y a plus de corrections à effectuer, je ne dois pas avoir de pied de page sous le graphique. (1 point pour le titre 1, 3 points pour le titre 2, 3 points pour le pied de page).
Et bien entendu, le graphique produit doit être le bon graphique… (3 points).

2-    Le second macro-programme doit produire les 25 graphiques représentatifs des échanges commerciaux que la France entretient avec ses 25 principaux partenaires européens. (5 points)

amusez vous bien

Hors ligne

 

#2 24-05-2018 13:30:17

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: Mon sujet de langage macro sous SAS

Les données sont dans ce fichier ZIP

Hors ligne

 

#3 25-05-2018 16:34:02

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: Mon sujet de langage macro sous SAS

bon... on n'est pas mercredi (et d'ailleurs j'ai posté le sujet hier et nous étions un jeudi...)

regardons un peu comment répondre aux questions posées...

en fait, le secret est dans la section 10.6.2... agir avec ordre et méthode... et surtout ne pas commencer par %macro monprogramme... parce que c'est le bouillon annoncé...

voici notre programme :

Code:

data cext2;
   set cext;
   solde=E1-I1;
   pctco=(e1+i1)/(sum(of e:)+sum(of i:));
run;

proc means data=cext2 noprint;
   ways 1 ;
   class date;
   format date year4.;
   var e1 i1 solde;
   output out=cext3 sum= exp imp solde;
run;

data cext3 ;
   set cext3;
   exp=12*exp/_freq_;
   imp=12*imp/_freq_;
   solde=12*solde/_freq_;
run;

title "Allemagne : Exportations, Importations et solde commercial";
Title2 "En mars 2018, ce pays représentait 24.2% de nos échanges";
title3 "avec nos 25 principaux partenaires commerciaux européens";
Footnote "Attention, pour 2018, on ne dispose en réalité que de 3 mois de données";
Footnote2 "pour rendre comparables les chiffres, on multiplie les données de 2018 par 12/3";
proc sgplot data=cext3 noautolegend;
   refline 0 / axis=y;
   series x=date y=exp / lineattrs=(thickness=2pt color=blue)  
                         curvelabel="Exportations" ;
   series x=date y=imp / lineattrs=(thickness=2pt color=red) 
                         curvelabel="Importations" ;
   series x=date y=solde / lineattrs=(thickness=2pt) 
                           curvelabel="Solde";
   xaxis display=(nolabel);
   yaxis display=(nolabel);
run;

introduisons un peu de macro-variable là dedans...

commençons par :

Code:

%let pays=Allemagne ;

et débrouillons nous pour produire un graphique correcte...

il faut déjà savoir quelles sont les séries relatives à l'Allemagne... pas de problème, c'est indiqué dans la table PAYS :

Code:

%let pays=Allemagne ;

data _null_;
   set pays(where=(pays="&pays"));
   call symputx("exp",exportation);
   call symputx("imp",importation);
run;
%put &exp &imp;

le %put nous permet de vérifier que ça marche. Changez la valeur de la macro-variable pays pour confirmer que ça fonctionne.

ensuite, ces macro-variables, il faut les utiliser :

Code:

data cext2;
   set cext;
   solde=&exp-&imp;
   pctco=(&exp+&imp)/(sum(of e:)+sum(of i:));
run;

et on va même un peu compléter ce code... nous avons besoin, pour la suite, du mois de l'observation la plus récente (en toute lettre, pour le titre du graphique) de l'année de l'observation la plus récente, de la valeur de pctco la plus récente et, une nouvelle fois du mois de l'observation la plus récente mais cette fois-ci en chiffres.

Cette donnée la plus récente, elle est sur la dernière ligne de la table CEXT, on va donc avoir besoin de l'option end= de SET :

Code:

data cext2;
   set cext end=last;
   solde=&exp-&imp;
   pctco=(&exp+&imp)/(sum(of e:)+sum(of i:));
   if last then do ;
      call symputx("annee",year(date));
      call symputx("mois_n,month(date));
      call symputx("pct",put(pctco,nlpct8.1));
      call symputx("mois_t",put(date,fradfmn.));
   end;
run;

vous allez dire 'mais ses étudiants connaissent pas coeur les noms des FORMAT "qui vont bien" ? ils sont trop forts !'

euh... ils avaient surtout droit à mon bouquin pendant l'épreuve...

bref, on a nos macro-variables, on est toujours en code ouvert, on peut donc facilement vérifier qu'elles ont les bonnes valeurs...

continuons :

Code:

proc means data=cext2 noprint;
   ways 1 ;
   class date;
   format date year4.;
   var &exp &imp solde;
   output out=cext3 sum= exp imp solde;
run;

pas vraiment de problème ici...

pour la suite, rien à modifier...

Code:

data cext3 ;
   set cext3;
   exp=12*exp/_freq_;
   imp=12*imp/_freq_;
   solde=12*solde/_freq_;
run;

arrive le graphique et on ne travaille en fait que les titres et pieds de page :
avant :

Code:

title "Allemagne : Exportations, Importations et solde commercial";
Title2 "En mars 2018, ce pays représentait 24.2% de nos échanges";
title3 "avec nos 25 principaux partenaires commerciaux européens";
Footnote "Attention, pour 2018, on ne dispose en réalité que de 3 mois de données";
Footnote2 "pour rendre comparables les chiffres, on multiplie les données de 2018 par 12/3";

après :

Code:

title "&pays : Exportations, Importations et solde commercial";
Title2 "En &mois_t &annee, ce pays représentait &pct de nos échanges";
title3 "avec nos 25 principaux partenaires commerciaux européens";
Footnote "Attention, pour &annee, on ne dispose en réalité que de &mois_n mois de données";
Footnote2 "pour rendre comparables les chiffres, on multiplie les données de &annee par 12/&mois_n";

le reste sans aucune modification... vous changez le nom du pays, vous vérifiez que ça marche et on peut passer au point suivant.

Evidemment, si vous indiquez ALLEMAGNE au lieu d'Allemagne, ça ne marche plus...

bon, ça n'est pas grave, on s'en sort très simplement :

Code:

%let pays=allemagne ;
%let pays=%sysfunc(propcase(&pays));

data _null_;
   set pays(where=(pays="&pays"));
   call symputx("exp",exportation);
   call symputx("imp",importation);
run;

**  le reste n'est pas modifié ;

Vous me direz "oui, mais si le pays n'existe pas, comment fait-on ?"

et je réponds "on s'adapte !"

(on pouvait faire de plein d'autres manières différentes)

Code:

%let pays=bliblo ;
%let pays=%sysfunc(propcase(&pays));

%let ctrl=0 ;

data _null_;
   set pays(where=(pays="&pays"));
   call symputx("exp",exportation);
   call symputx("imp",importation);
   if pays="&pays" then call symputx("ctrl",1);
run;

si le pays existe, ctrl=1, sinon il vaut 0.

et que fait t-on ensuite ?

ben... quand on construira notre macro programme, on aura un embranchement  :

Code:

%if &ctrl=1 %then %do ;
et on construira le graphique ;
%end;

%else %do ;
et on produira un message ;
%end;

Le %let qui précède l'étape DATA est important : si vous l'enlevez et si le pays n'existe pas, la macro variable ctrl n'est pas construite et l'idée de baser une condition sur une macro variable qui n'existe pas ne me plait guère... mais c'est tout à fait possible puisque vous disposez d'une macro fonction %SYMEXIST qui vous indique si une macro variable existe ou pas.

Plus besoin de définir ctrl avant l'étape data et votre embranchement devient :

Code:

%if %symsexist(ctrl) %then %do ;
et on construira le graphique ;
%end;

%else %do ;
et on produira un message ;
%end;

de façon alternative, quand on connait la macro variable automatique SYSNOBS (qui vous indique le nombre d'observation de la dernière table créé), on peut aussi procéder de la façon suivante :

Code:

%let pays=bliblo ;
%let pays=%sysfunc(propcase(&pays));

data ee;
   set pays(where=(pays="&pays"));
   call symputx("exp",exportation);
   call symputx("imp",importation);
run;

%if &sysnobs=1 %then %do ;
et on construira le graphique ;
%end;

%else %do ;
et on produira un message ;
%end;

SYSNOBS ne fonctionne pas avec une data _null_, il faut créer une table...

enfin, dernière partie chose à préparer avant d'introduire %MACRO / %MEND : si le pays n'existe pas, il faut produire un message présentant la liste de pays possible.

C'est facile avec PROC SQL mais mes étudiants ne connaissent pas PROC SQL... mais comme ils connaissent bien mon livre, ils se souviennent du programme 3.77 et ils l'adaptent.

Code:

data _null_;
   set pays end=last ;
   length liste $ 500 ;
   retain liste ;
   liste=catx(" ",liste,pays);
   if last then call symputx("liste",liste);
run;

on est maintenant prêt à introduire %macro / %mend.

à suivre

Hors ligne

 

#4 02-06-2018 20:50:43

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: Mon sujet de langage macro sous SAS

les beaux mercredis un samedi soir... on aura tout vu...

bref,

introduisons %macro / %mend

l'essentiel du travail a été fait, il ne nous reste en fait pas grand chose à faire...

Code:

%macro test(pays) ;

%let pays=%sysfunc(propcase(&pays));

%let ctrl=0 ;

data _null_;
   set pays(where=(pays="&pays"));
   call symputx("exp",exportation);
   call symputx("imp",importation);
    if pays="&pays" then call symputx("ctrl",1);
run;

%if &ctrl=1 %then %do ;

data cext2;
   set cext end=last;
   solde=&exp-&imp;
   pctco=(&exp+&imp)/(sum(of e:)+sum(of i:));
   if last then do ;
      call symputx("annee",year(date));
      call symputx("mois_n",month(date));
      call symputx("pct",put(pctco,nlpct8.1));
      call symputx("mois_t",put(date,fradfmn.));
   end;
run;

proc means data=cext2 noprint;
   ways 1 ;
   class date;
   format date year4.;
   var &exp &imp solde;
   output out=cext3 sum= exp imp solde;
run;

data cext3 ;
   set cext3;
   exp=12*exp/_freq_;
   imp=12*imp/_freq_;
   solde=12*solde/_freq_;
run;

title "&pays : Exportations, Importations et solde commercial";
Title2 "En &mois_t &annee, ce pays représentait &pct de nos échanges";
title3 "avec nos 25 principaux partenaires commerciaux européens";

%if %mois_n ne 12 %then %do ;
Footnote "Attention, pour &annee, on ne dispose en réalité que de &mois_n mois de données";
Footnote2 "pour rendre comparables les chiffres, on multiplie les données de &annee par 12/&mois_n";
%end;

proc sgplot data=cext3 noautolegend;
   refline 0 / axis=y;
   series x=date y=exp / lineattrs=(thickness=2pt color=blue)  
                         curvelabel="Exportations" ;
   series x=date y=imp / lineattrs=(thickness=2pt color=red) 
                         curvelabel="Importations" ;
   series x=date y=solde / lineattrs=(thickness=2pt) 
                           curvelabel="Solde";
   xaxis display=(nolabel);
   yaxis display=(nolabel);
run;

proc datasets nolist ;
delete cext2-cext3;
quit;
title;
footnote;

%end;

%else %do ;

data _null_;
   set pays end=last ;
   length liste $ 500 ;
   retain liste ;
   liste=catx(" ",liste,pays);
   if last then call symputx("liste",liste);
run;

%put %str(Le pays que vous avez demandé n%'est pas dans la liste des pays possibles (ou alors, vous l%'avez mal orthographié…); %put Voici la liste des pays pour lesquels le macro-programme peut produire un graphique :;
%put &liste ;

%end;

%mend

pas plus compliqué que cela (puisque nous avons tout préparé, en code ouvert, avant.

quelques "ajouts" suite à la construction du graphique :

Code:

proc datasets nolist ;
delete cext2-cext3;
quit;
title;
footnote;

l'idée, ici, c'est "d'effacer" ce que le macro programme a créé.

Si vous modifiez votre macro programme et que vous obtenez un résultat, bien souvent, vous ne regardez pas votre journal en vous disant "j'ai un résultat, c'est donc que mon programme marche".

il est tout à fait possible que ce résultat ait été construit en utilisant des éléments d'une autre exécution.....

donc, pour éviter cela, on supprime ce que le macro programme a crée : tables intermédiaires, titres, pieds de page etc...

en passant, les programmes du précédent post et celui du post présent ont été écrits sans que je puisse vérifier s'ils fonctionnent (pas de SAS à ma disposition...) - en cas de problème, me contacter...

mais si tout fonctionne bien, j'ai déjà 15/20

nous verrons prochainement comment avoir 20/20 en répondant à la dernière question...

à suivre

Hors ligne

 

#5 04-06-2018 13:40:39

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: Mon sujet de langage macro sous SAS

Terminons cette correction.

on souhaite maintenant un macro programme qui nous permet de produire l'ensemble des graphiques. Nous allons bien entendu fortement recycler notre premier macro programme :

on va commencer de la façon suivante :

Code:

%macro test2 ;

data _null_ ;
   set pays end=last;
   call symputx(compress("pays"||_n_),pays);
   call symputx(compress("exp"||_n_),exportation);
   call symputx(compress("imp"||_n_),importation);
   if last then call symputx("nbpays",_n_);
run;

il s'agit ici de créer autant de macro variables pays, exp et imp que nous avons de pays à analyser.
Dans la macro-variable NBPAYS se trouve le nombre de pays à représenter.

ensuite... boucle %DO...

Code:

%do i=1 %to &nbpays;

data cext2;
   set cext end=last;
   solde=&&exp&i-&&imp&i;
   pctco=(&&exp&i+&&imp&i)/(sum(of e:)+sum(of i:));
   if last then do ;
      call symputx("annee",year(date));
      call symputx("mois_n",month(date));
      call symputx("pct",put(pctco,nlpct8.1));
      call symputx("mois_t",put(date,fradfmn.));
   end;
run;

proc means data=cext2 noprint;
   ways 1 ;
   class date;
   format date year4.;
   var &&exp&i &&imp&i solde;
   output out=cext3 sum= exp imp solde;
run;

il nous suffit en fait d'adapter l'appel des macro variables...

le reste est sans changement

Code:

data cext3 ;
   set cext3;
   exp=12*exp/_freq_;
   imp=12*imp/_freq_;
   solde=12*solde/_freq_;
run;

title "&pays : Exportations, Importations et solde commercial";
Title2 "En &mois_t &annee, ce pays représentait &pct de nos échanges";
title3 "avec nos 25 principaux partenaires commerciaux européens";

%if %mois_n ne 12 %then %do ;
Footnote "Attention, pour &annee, on ne dispose en réalité que de &mois_n mois de données";
Footnote2 "pour rendre comparables les chiffres, on multiplie les données de &annee par 12/&mois_n";
%end;

proc sgplot data=cext3 noautolegend;
   refline 0 / axis=y;
   series x=date y=exp / lineattrs=(thickness=2pt color=blue)  
                         curvelabel="Exportations" ;
   series x=date y=imp / lineattrs=(thickness=2pt color=red) 
                         curvelabel="Importations" ;
   series x=date y=solde / lineattrs=(thickness=2pt) 
                           curvelabel="Solde";
   xaxis display=(nolabel);
   yaxis display=(nolabel);
run;

proc datasets nolist ;
delete cext2-cext3;
quit;

title;
footnote;

%end;

%mend;

et voilà !

vous avez 20/20

Hors ligne

 

Pied de page des forums

Propulsé par FluxBB
Traduction par FluxBB.fr
Flux RSS