IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macro Discussion :

[Macro] appel à une fonction/routine dans une étape DATA


Sujet :

Macro

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 24
    Points : 24
    Points
    24
    Par défaut [Macro] appel à une fonction/routine dans une étape DATA
    Bonjour à tous,

    je me permets de poster ici car je me galère depuis vendredi matin avec ce pb que je ne parviens pas à résoudre

    en entrée : une table et 2 variables var1 et var2

    sortie souhaitée :

    var1 var2 var3
    1 2 f(1,2)
    5 7 f(5,7)
    9 4 f(9,4)

    où f(5,7) est le résultat d'une fonction quelconque dépendant de var1 et var2, lorsque var1=5 et var=2=7

    Dans mon cas précis, cette fonction ne peut s'exprimer que par un comptage issu d'une requête SQL dépendant de var1 et var2 :

    select count(*) from ......where ......between var1 et var2.

    Je veux donc pouvoir récupérer l'info issue de ce comptage pour renseigner ma variable var3.

    J'ai donc imaginé dans un prmier temps,
    - créer une macro dans laquelle j'éxexute un select count(*) into:myvar........
    - faire appel dans une étape DATA à la macro à l'aide d'un call execute
    - récupérer la contenu de &myvar et l'affecté à var3.

    Tout ça ne fonctionne pas et je ne dois pas être sur la bonne voie.
    Ce qui est sûr c'est que je suis obligé d'utiliser cette requête pour calculer var3 ( pas possible de contourner la difficulté de cette manière).

    en tout cas, merci à tous ceux qui auront pris le temps de lire ce mail et merci d'avance pour vos sggestions !!!!

    Vince

  2. #2
    Expert confirmé
    Avatar de olivier.decourt
    Homme Profil pro
    Formateur R/SAS/statistiques
    Inscrit en
    Avril 2008
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Formateur R/SAS/statistiques
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 064
    Points : 4 478
    Points
    4 478
    Par défaut
    Bonjour Vince.
    Déjà, ce qu'il faut bien comprendre avec un macro-programme, c'est qu'il ne fait qu'un copier/coller, et pas une parenthèse dans l'exécution du programme SAS. Donc mettre une proc SQL dans un macro-programme appelé depuis une étape Data, ça revient à écrire le SQL en plein milieu de l'étape Data : forcément, ça ne fonctionne pas.
    Le second point, quand on écrit DATA ... ; ... ; %mon_macro_pgm(...) ; RUN ; on n'appelle pas le macro-programme pendant l'exécution de l'étape Data (et il n'est pas exécuté à chaque observation). Le compilateur macro passe une fois avant toute exécution, remplace %mon_macro_pgm(...) ; par le code que le macro-programme contient, et laisse ensuite le compilateur SAS exécuter le tout.
    C'est pour ça que toutes les transmissions d'information entre le monde SAS (variables, tables) et le monde macro sont si tortueuses (CALL SYMPUT) !

    Par contre, en tripotant un peu de SQL, avec une requête imbriquée corrélée (oui, dit comme ça ce n'est pas très engageant, voir exemple ci-dessous), on y arrive avec du code assez sobre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    DATA work.ages ;
    	INPUT ageMin ageMax ;
    CARDS ;
    12 15
    11 13
    10 17
    14 14
    8 10
    ;
    RUN ;
     
    PROC SQL ;
    	CREATE TABLE work.resultat AS
    		SELECT a.*,
    			   (SELECT COUNT(*) FROM sashelp.class WHERE age BETWEEN a.ageMin AND a.ageMax) AS nb
    		FROM work.ages AS a
    	;
    QUIT ;
    Olivier
    Bon courage.
    Olivier

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 24
    Points : 24
    Points
    24
    Par défaut
    merci Olivier pour ces eclaircissements.
    Je n'avais pas pas pensé à la requête imbriquée, parfait dans l'immédiat

    Pour en revenir à mon pb, si on généralise en occultant ma "contrainte" SQL, est-ce à dire que SAS ne permet pas la création de fonctions / procédures comme cela existe dans certains langages , appelables en cours d'éxécution et retournant des valeurs exploitables à l'exécution ? ( vieux souvenir de cours de programmation en C .... ) ?

    Vincent

  4. #4
    Expert confirmé
    Avatar de olivier.decourt
    Homme Profil pro
    Formateur R/SAS/statistiques
    Inscrit en
    Avril 2008
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Formateur R/SAS/statistiques
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 064
    Points : 4 478
    Points
    4 478
    Par défaut
    C'est prévu pour la version 9.2, avec la proc FCMP (Function CoMPiler). Mais sinon, SAS est un langage qui incitera plutôt à générer plusieurs étapes de calcul (avec du macro-langage ou avec des CALL EXECUTE) et à récupérer les résultats dans une table SAS qu'on bricole ensuite.
    Petit essai en imaginant qu'on veuille récupérer la médiane (une proc Means la calculera) des poids pour les enfants avec un âge compris entre les min et max inscrits dans une table.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    DATA work.ages ;
        INPUT ageMin ageMax ;
    CARDS ;
    12 15
    11 13
    10 17
    14 14
    ;
    RUN ;
    ODS EXCLUDE ALL ;
    DATA _NULL_ ;
    	SET work.ages END = fin ;
    	CALL EXECUTE("ODS OUTPUT summary=work.stat ;") ;
    	CALL EXECUTE("PROC MEANS DATA=sashelp.class MEDIAN ;") ;
    	CALL EXECUTE("WHERE age BETWEEN "!!ageMin!!" AND "!!ageMax!!" ;") ;
    	CALL EXECUTE("VAR weight ;") ;
    	CALL EXECUTE("RUN ;") ;
    	CALL EXECUTE("PROC APPEND BASE=work.medianes DATA=work.stat ;") ;
    	CALL EXECUTE("RUN ;") ;
    RUN ;
    ODS SELECT ALL ;
    DATA work.medianes ;
    	MERGE work.ages work.medianes ;
    RUN ;
    Olivier
    Bon courage.
    Olivier

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 02/07/2013, 20h49
  2. appeler une fonction php dans une fonction javaScript
    Par geeksDeve dans le forum Langage
    Réponses: 3
    Dernier message: 17/04/2012, 15h30
  3. Réponses: 10
    Dernier message: 14/03/2009, 13h36
  4. Réponses: 1
    Dernier message: 25/10/2007, 21h25
  5. [VBA-E] Une fonction Excel dans une fonction VBA
    Par laloune dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 14/07/2006, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo