Précédent   Forum du club des développeurs et IT Pro > 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
 
Outils de la discussion
Publicité
'
Vieux 06/01/2013, 23h54   #1
yedid
Invité de passage
 
Inscription : juillet 2007
Messages : 49
Détails du profil
Informations forums :
Inscription : juillet 2007
Messages : 49
Points : 2
Points : 2
Par défaut Macro et proc sql

Bonjour à tous!

Je suis un peu débutant en sas et je bug depuis plusieurs heures sur le même problème.

J'ai une table hdrs qui à la forme suivante :

Patient Visite Score1 Score2 Score3 ....

0 J0 1 3 2 ....
0 J4 2 10 3 ....
1 J0 6 3 2 ...

Il y a théoriquement 8 visites par patients. Certains patients n'ayant pas assisté à une visite n'auront pas la ligne correspondante.

J'aimerai pouvoir dans ce cas tout de même leur rajouter une ligne avec le couple Patient/Visite correspondant, et le reste en données manquantes . . . . . .

Voila comment j'ai procédé :

1) La macro

Voici la macro:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
%macro insertHDRS(numpat,numvisit);
proc sql noprint;
    SELECT DISTINCT count(*) INTO :nobserv FROM hdrs WHERE numero=&numpat AND visit="&numvisit";
quit;
 
%IF  (&nobserv  = 0) %then
%do;
proc sql noprint;
    INSERT INTO hdrs(numero,visit) VALUES(&numpat,"&numvisit",);
quit;
%end;
%mend insertHDRS;

2) La fonction qui l'appelle

Code :
1
2
3
4
5
6
7
8
DATA _null_ ;
length j $ 3;
do i = 0 TO 191;
 do j= 'J0','J4','J7','J14','J21','J28','J42','J56';
    call execute('%insertHDRS('|| i||','||j||')');
 end;
end;
run;

Malheureusement, le code m'insère les visites pour tous les patients à toutes les visites sans filtrer celles qui sont déjà dans la table (le if de la macro ne fait pas son effet)
Je pense que ca doit être du à un pb de la macro variable &nobserv , mais je ne sais pas pourquoi??

Quelqu'un aurait il une idée??

Merci d'avance pour votre aide!
yedid est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 08h47   #2
edward carnby
Membre éprouvé
 
Homme Ludovic Le Breton
Statisticien/développeur BI
Inscription : janvier 2012
Messages : 177
Détails du profil
Informations personnelles :
Nom : Homme Ludovic Le Breton
Âge : 38
Localisation : France, Oise (Picardie)

Informations professionnelles :
Activité : Statisticien/développeur BI
Secteur : Transports

Informations forums :
Inscription : janvier 2012
Messages : 177
Points : 464
Points : 464
Bonjour,

J'aurais fait plus simple ...
1/ création d'une table de référence de la liste des visites.
2/ création de tous les couples patient/visite possible
3 création de la table finale avec les manquants

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 
/* jeu de données */
DATA test;
input Patient Visite$ Score1 Score2 Score3;
cards;
0 J0 1 3 2
0 J4 2 10 3
0 J7 2 10 3
0 J14 2 10 3
0 J21 2 10 3
0 J28 2 10 3
0 J42 2 10 3
0 J56 2 10 3
1 J7 6 3 2
1 J14 6 3 2
1 J0 6 3 2
1 J21 6 3 2
1 J56 6 3 2
2 J0 6 3 2
2 J7 6 3 2
2 J14 6 3 2
2 J42 6 3 2
;
run;
 
/* table des visites */
DATA visite;
input visite$;
cards;
J0
J4
J7
J14
J21
J28
J42
J56
;
run;
 
/* table des couples patients / visites */
proc sql;
	CREATE TABLE patient_visite AS SELECT DISTINCT t1.patient, t2.visite
	FROM test AS t1, visite AS t2
	ORDER BY patient;
quit;
 
/* table finale avec les manquants */
proc sql;
	CREATE TABLE finale AS SELECT
		coalesce(t1.patient,t2.patient) 	AS	patient,
		coalesce(t1.visite,t2.visite) 	AS	visite,
		coalesce(t1.Score1,.) 	AS	Score1,
		coalesce(t1.Score2,.) 	AS	Score2,
		coalesce(t1.Score3,.) 	AS	Score3
	FROM test AS t1 RIGHT JOIN patient_visite AS t2 ON (t1.patient=t2.patient AND t1.visite=t2.visite)
	ORDER BY patient, visite;
quit;
edward carnby est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 09/01/2013, 12h24   #3
jmarandet
Membre du Club
 
Homme julien marandet
Ingénieur Statisticien
Inscription : janvier 2013
Messages : 28
Détails du profil
Informations personnelles :
Nom : Homme julien marandet
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Ingénieur Statisticien
Secteur : Service public

Informations forums :
Inscription : janvier 2013
Messages : 28
Points : 54
Points : 54
Effectivement, la réponse d'edward carnby est plus logique si l'on maîtrise les jointures SQL.
Elle sera aussi plus performante si vous devez prendre en charge de gros volumes de données.

Maintenant, pour répondre spécifiquement au problème que vous avez observé et vous fournir une explication sur le fonctionnement de votre macro.

En fait, votre code est dans l'ensemble juste. Le seul problème vient de votre PROC SQL où vous comptez le nombre de lignes pour un couple patient/visite donné.
Lorsqu'il n'y a aucune observation la PROC SQL n'instancie pas de macro-variable : Votre méthode ne vous permet donc jamais de savoir si le couple patient/visite n'est pas présent dans votre table !

Pour contourner ce problème, soit vous utilisez ma macro-variable système &sqlobs qui est indiquée à chaque PROC SQL, soit vous utilisez les macro-fonctions %symexist() pour vous assurer que votre décompte a été instancié par la PROC SQL.

Un exemple qui marche :
Code :
1
2
3
4
5
6
7
8
9
10
11
%macro insertHDRS(numpat,numvisit);
	proc sql noprint feedback;
	    SELECT DISTINCT * FROM hdrs WHERE numero=&numpat AND visit="&numvisit";
	quit;	 
	%IF  (&sqlobs eq 0) %then
	%do;
		proc sql noprint;
		    INSERT INTO hdrs2(numero,visit) VALUES(&numpat,"&numvisit",);
		quit;
	%end;
%mend insertHDRS;
jmarandet est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/01/2013, 14h49   #4
jerome_pdv2
Membre chevronné
 
Homme
statisticien
Inscription : mai 2011
Messages : 401
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : statisticien
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : mai 2011
Messages : 401
Points : 730
Points : 730
Bonjour,
question con et hors sujet, mais c'est au sujet du post précédent

Citation:
PROC SQL n'instancie pas de macro-variable
Le verbe "instancier" veut dire quoi ? (vu que ce n'est pas dans le/mon dico)

A première vue ça semble vouloir dire "initialiser" "créer"

Citation:
votre décompte a été instancié par la PROC SQL.
mais je ne suis pas persuadé que ce terme signifie exactement ce que je peux supposer.
__________________
[...] Le SASSAGE s'il existe, a pour but de purifier les différentes semoules pour une meilleur efficacité de la mouture (par aspiration et tamisage) [...]
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/01/2013, 15h23   #5
jmarandet
Membre du Club
 
Homme julien marandet
Ingénieur Statisticien
Inscription : janvier 2013
Messages : 28
Détails du profil
Informations personnelles :
Nom : Homme julien marandet
Localisation : France, Rhône (Rhône Alpes)

Informations professionnelles :
Activité : Ingénieur Statisticien
Secteur : Service public

Informations forums :
Inscription : janvier 2013
Messages : 28
Points : 54
Points : 54
Non votre question n'est pas comme vous la qualifiez...

C'est bien cela, la variable n'est pas créée, elle n'existe pas, tant qu'elle n'est pas instanciée.

Comme la PROC SQL est située dans un code macro, la variable &nobserv que vous souhaitiez créer n'existe, ne "vit", que dans l'environnement local de la macro.
A la fin de l'exécution de la macro, la variable &nobserv est jetée aux oubliettes, elle n'existe plus, car l'environnement interne de la macro n'a plus lieu d'être.

Ainsi, à la seconde exécution de la macro, la PROC SQL va de nouveau instantier la variable &nbserv, si jamais la requête comporte au moins une ligne...

Pour savoir si une macro-variable existe (est instanciée), il existe des fonctions dédiées, comme %symexist, %symglobl et %symlocal.
Sinon il existe la vue SASHELP.VMACRO qui indique l'ensemble des macro-variables disponibles...
jmarandet est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/01/2013, 09h32   #6
s_a_m
Modérateur
 
Homme Samir SELMANE
Consultant en Business Intelligence
Inscription : février 2011
Messages : 1 310
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 310
Points : 2 541
Points : 2 541
Hello,
Personnellement,j'aurai fait :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
DATA test;
input Patient Visite$ Score1 Score2 Score3;
cards;
0 J0 1 3 2
0 J4 2 10 3
0 J7 2 10 3
0 J14 2 10 3
0 J21 2 10 3
0 J28 2 10 3
0 J42 2 10 3
0 J56 2 10 3
1 J7 6 3 2
1 J14 6 3 2
1 J0 6 3 2
1 J21 6 3 2
1 J56 6 3 2
2 J0 6 3 2
2 J7 6 3 2
2 J14 6 3 2
2 J42 6 3 2
;
run;
proc sql;
	CREATE TABLE tab AS SELECT DISTINCT 
	b.visite,b.patient ,a.score1, a.score2,a.score3 FROM test AS a 
	RIGHT JOIN (SELECT * FROM test(keep =patient),test (keep=visite)) AS b
	ON a.visite=b.visite AND a.patient=b.patient
	ORDER BY patient,visite;
quit;
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 22h47.


 
 
 
 
Partenaires

Hébergement Web