Précédent   Forum des professionnels en informatique > Logiciels > Solutions d'entreprise > Business Intelligence > SAS > Macro
Macro Forum d'entraide sur le langage Macro de SAS
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 18/05/2011, 14h55   #1
Invité de passage
 
Femme
statisticienne
Inscription : mai 2011
Messages : 3
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : statisticienne
Secteur : Santé

Informations forums :
Inscription : mai 2011
Messages : 3
Points : 1
Points : 1
Par défaut macro variable numérique?

Bonjour à tous,

J'ai un petit souci dans ma programmation que je ne m'explique pas...

Dans une macro :
J'ai une variable, dont je récupère le minimum dans une table SAS. Avec un call symput, j'attribue cette valeur à une macro-variable.
Je cherche ensuite (et c'est là que j'ai un souci!) à avoir une condition sur la suite de la macro sur cette macro variable. Le problème est que cette condition est "si macro-variable<0", et que SAS la reconnait comme caractère et non numérique. Et avec un %eval, ça ne marche pas non plus...

Voilà ma macro (simplifiée au maximum pour cet exemple) :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%macro test(tabin, var);
 
proc univariate DATA=&tabin noprint; var &var; output out=temp0 min=min;
run;
DATA NULL; SET temp0;
call symput('Min',min);
run;
 
%put Mininimum = &Min;
 
%IF (%eval(&Min)<0) %then %do;
%put toto;
%end;
 
%mend;
=> SAS n'arrive pas à reconnaitre en ma macro-variable Min une variable numérique, malgré le %eval...

Avez-vous une idée?
Merci d'avance pour toute piste!!
sofisaas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/05/2011, 15h02   #2
Membre Expert
 
Homme
Biostatisticien
Inscription : juin 2009
Messages : 1 143
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Irlande

Informations professionnelles :
Activité : Biostatisticien
Secteur : Industrie Pharmaceutique

Informations forums :
Inscription : juin 2009
Messages : 1 143
Points : 1 760
Points : 1 760
Bonjour,

Pour commencer je te propose une autre syntaxe via la proc sql qui évite de créer une table temporaire et optimise le traitement:

Code :
1
2
3
4
proc sql;
SELECT min(&var) INTO :minvar
FROM &tabin
; quit;
au lieu de :

Code :
1
2
3
4
5
proc univariate DATA=&tabin noprint; var &var; output out=temp0 min=min;
run;
DATA NULL; SET temp0;
call symput('Min',min);
run;
les macros variables sont enregistrées au type caractère, y a rien qu'on puisse faire la dessus. mais normalement ca passe quand même lorsque l'on utilise du numérique. ca donne quoi sans le %eval. D'une manière générale, je te conseille plutôt d'utiliser la macro fonction %sysevalf. Sinon tu n'as pas à priori besoin du %do %end, bien que cette sécurité ne soit pas gênante en soit. Elle dit quoi la log?
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/05/2011, 15h05   #3
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 006
Détails du profil
Informations personnelles :
Nom : Homme Samir SELMANE
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : février 2011
Messages : 1 006
Points : 1 703
Points : 1 703
tes instructions sont un peu trop mal placées.

on utilise le
pour ne pas créer une table.

le call symput est une façon s'assigner des macros variables à des OBS, et là toi tu ne récupére qu'une seule valeur. donc un %let pourra faire l'affaire.
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/05/2011, 15h22   #4
Invité de passage
 
Femme
statisticienne
Inscription : mai 2011
Messages : 3
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : statisticienne
Secteur : Santé

Informations forums :
Inscription : mai 2011
Messages : 3
Points : 1
Points : 1
Merci pour vos réponses!

Super pour l'astuce de la proc sql Manoutz, je n'y pense jamais à celle là!
Citation:
Sinon tu n'as pas à priori besoin du %do %end, bien que cette sécurité ne soit pas gênante en soit.
C'est qu'en réalité j'ai beaucoup plus d'instructions que %put toto (!) et j'ai oublié de les enlever, j'ai simplifié le code au maximum pour vous montrer mon problème...

Voici mon code amélioré:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
%macro test(tabin, var);
 
proc sql;
SELECT min(&var) INTO :minvar
FROM &tabin
; quit;
 
%put Mininimum = &Minvar;
%IF (%eval(&Minvar)<0) %then %do;
%put toto;
%end;
%mend;
Cependant, cela ne marche toujours pas. La log dit :

Code :
1
2
3
4
Mininimum = -3.27591
ERROR: Opérande caractère trouvé dans la fonction %EVAL ou condition %IF là où un opérande numérique
       est requis. La condition était : -3.27591
ERROR: L'exécution de la macro TEST va s'arrêter.

Merci s_a_m pour ta réponse, mais je ne peux pas faire un %let parce que la valeur que je veux récupérer est dans une table SAS, ce n'est pas comme si je savais à l'avance que je voulais écrire %let minvar=-3, là ça va dépendre à chaque fois des données. Pour le data _null_, oui c'est pour ne pas créer de table, ici effectivement je ne veux pas en créer mais recueillir une valeur dans une table pour en faire une condition...
sofisaas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/05/2011, 15h26   #5
Invité de passage
 
Femme
statisticienne
Inscription : mai 2011
Messages : 3
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : statisticienne
Secteur : Santé

Informations forums :
Inscription : mai 2011
Messages : 3
Points : 1
Points : 1
Ah excusez-moi, il y avait beaucoup de choses dans vos réponses j'ai oublié de tout tester!

Sans le %eval j'avais le même message d'erreur, mais en utilisant %sysevalf cela marche parfaitement, plus d'erreur, c'est génial. MERCI!!!
sofisaas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/05/2011, 15h27   #6
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 006
Détails du profil
Informations personnelles :
Nom : Homme Samir SELMANE
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : février 2011
Messages : 1 006
Points : 1 703
Points : 1 703
utilise plutot %unquote et non pas %eval ( qui sert pour les calcules )
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/05/2011, 10h30   #7
Membre habitué
 
Femme Géraldine CADE DESCHAMPS
Support Clients SAS (France et Europe)
Inscription : février 2010
Messages : 62
Détails du profil
Informations personnelles :
Nom : Femme Géraldine CADE DESCHAMPS
Localisation : France

Informations professionnelles :
Activité : Support Clients SAS (France et Europe)
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : février 2010
Messages : 62
Points : 139
Points : 139
Bonjour,

C'est LA REGLE ESSENTIELLE en macro : une macro-variable c'est du texte, rien que du texte ! Il faut utiliser les fonctions macros si l'on veut la traiter en numérique, faire des traitements dessus etc.

Géraldine Deschamps
Géraldine_Cade_SAS est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/05/2011, 10h47   #8
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 006
Détails du profil
Informations personnelles :
Nom : Homme Samir SELMANE
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : février 2011
Messages : 1 006
Points : 1 703
Points : 1 703
Bonjour,
oui une macro variable est une chaine de caractère. Mais le système ne l'interprète pas toujours de tel.
Exemple.

Code :
1
2
3
4
5
6
7
8
 
 
%let a=14;
 
 
proc sql;
 SELECT * FROM sashelp.class WHERE age  =&a.;
quit;

et j'ai eu ce résultat:

Code :
1
2
3
4
5
6
7
8
9
10
 
                         Le Système SAS                        3
                                    10:42 Thursday, May 19, 2011
 
          Name      Sex       Age    Height    Weight
          ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
          Alfred     M          14        69        112.5
          Carol      F           14      62.8       102.5
          Henry     M          14      63.5       102.5
          Judy       F          14      64.3         90
on dirai que SAS a intérpreter ma macro variable comme du numérique. !!!
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/05/2011, 16h23   #9
Expert Confirmé
 
Avatar de olivier.decourt
 
Homme Olivier Decourt
Formateur en informatique
Inscription : avril 2008
Messages : 1 467
Détails du profil
Informations personnelles :
Nom : Homme Olivier Decourt
Âge : 34
Localisation : France

Informations professionnelles :
Activité : Formateur en informatique
Secteur : Conseil

Informations forums :
Inscription : avril 2008
Messages : 1 467
Points : 2 823
Points : 2 823
Non, SAM, ta macro-variable est bien restée du texte.
C'est le texte 14 (c'est à dire 1 puis 4) qui a été copié par le compilateur macro dans le texte du code SAS, après le signe =.

Il faut bien distinguer le compilateur macro, qui considère les macro-variables (et quasiment tout ce qui lui passe sous la main d'ailleurs) comme du texte, et le compilateur SAS, qui n'a accès à rien de ce que fait le compilateur macro et en subit uniquement les conséquences.
L'ordre d'exécution de ta proc SQL est :
1) le compilateur macro passe : presque tout est du texte qui l'indiffère, seul le &age retient son attention. Il remplace le texte &a par le texte 14.
2) le compilateur SAS se voit transmettre le résultat de l'étape 1. Il interprète la valeur 14 comme un nombre mais ne sait pas que ça provient d'une macro-variable. Ca aurait tout aussi bien pu être en dur dans le code.
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/05/2011, 17h10   #10
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 006
Détails du profil
Informations personnelles :
Nom : Homme Samir SELMANE
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : février 2011
Messages : 1 006
Points : 1 703
Points : 1 703
Merci Olivier pour les explications plus précises.
Je n'ai pas précisé qu'il y a un compilateur marco et compilateur SAS qui Interprète le code ( que j'ai appelé système).

Mais le compilateur SAS n'interprète pas toujours tout ce qui est chiffre comme du numérique?!!!
alors j'ai fais ce teste:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
 
%let a=14;
 
DATA test;
SET sashelp.class;
caractere= put (age,2.); /*PS: j'ai pas mis de $ pour éviter le warning comme quoi la variable est déjà numérique*/
run;
 
proc sql;
SELECT * FROM test WHERE caractere=&a.;
quit;
message LOG:
Code :
1
2
3
4
 
ERROR: L'expression utilisant égal (=) a des composants qui
       sont de différents types de données.
370  quit;

mais avec :
Code :
1
2
3
4
 
proc sql;
SELECT * FROM test WHERE caractere="&a";
quit;
sa me donne bien le résultat attendu.
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 13h35   #11
Membre habitué
 
Sébastien Ringuedé
Inscription : janvier 2011
Messages : 61
Détails du profil
Informations personnelles :
Nom : Sébastien Ringuedé
Localisation : France, Loiret (Centre)

Informations forums :
Inscription : janvier 2011
Messages : 61
Points : 114
Points : 114
Bonjour

dans ton programme, tu indiques :

Code :
1
2
3
 
caractere= put (age,2.); /*PS: j'ai pas mis de $ pour éviter le warning comme quoi la variable est déjà numérique*/
run;
le "déjà" du PS me pose problème puisque tu utilises la fonction PUT, quel que soit le FORMAT utilisé, la variable créé est une variable caractère.

aussi, quand tu indiques :
Code :
1
2
3
4
 
proc sql;
SELECT * FROM test WHERE caractere=&a.;
quit;
ça ne peut pas fonctionner : CARACTERE est une variable caractère, si tu veux citer une modalité, il faut, puisque la variable est caractère, la préciser entre quotes.

a+
z6c3po est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 14h41.


 
 
 
 
Partenaires

Hébergement Web