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 17/11/2011, 23h03   #1
Membre régulier
 
Femme Mariam
Statisticienne-Consultante BI
Inscription : avril 2008
Messages : 127
Détails du profil
Informations personnelles :
Nom : Femme Mariam
Localisation : Canada

Informations professionnelles :
Activité : Statisticienne-Consultante BI
Secteur : Conseil

Informations forums :
Inscription : avril 2008
Messages : 127
Points : 96
Points : 96
Par défaut Optimisation en macro d'une boucle Do Select when

Bonjour,

J'ai un programme de base que je dois optimiser en macro programme.
D'après ce que j'ai compris il permet de lineariser les données.
Je m'explique :
Les données sources sont sous la forme (exemple):
NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM MN_MEN_CAL_PRE AN_DEB_PRE AN_FIN_PRE
1 2 29 1992 1993
1 2 50 1994 1994
1 2 50 2001 2001

A la fin je voudrais avoir :
NO_SEQ_CLI_BEN 1
NO_SEQ_PRE_DEM 2
MN_MEN_CAL_PRE 50
AN_DEB_PRE 1992
AN_FIN_PRE 2001
Mn_31_dec_1970 0
.....
Mn_31_dec_1992 29
Mn_31_dec_1993 29
Mn_31_dec_1994 50
.....
Mn_31_dec_2001 50
....
Mn_31_dec_2010 0

Voici le programme qui marche bien:
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
DATA DATA1;
     SET DATA1;
 
BY NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM AN_DEB_PRE;
 
	 IF FIRST.NO_SEQ_PRE_DEM THEN DO;
 
   MN_31_DEC_1970 = 0;   MN_31_DEC_1971 = 0; MN_31_DEC_1972 = 0; MN_31_DEC_1973 = 0;  
   MN_31_DEC_1974 = 0;   MN_31_DEC_1975 = 0; MN_31_DEC_1976 = 0; MN_31_DEC_1977 = 0;    
   MN_31_DEC_1978 = 0;   MN_31_DEC_1979 = 0; MN_31_DEC_1980 = 0; MN_31_DEC_1981 = 0;     
   MN_31_DEC_1982 = 0;   MN_31_DEC_1983 = 0; MN_31_DEC_1984 = 0; MN_31_DEC_1985 = 0;    
   MN_31_DEC_1986 = 0;   MN_31_DEC_1987 = 0; MN_31_DEC_1988 = 0; MN_31_DEC_1989 = 0;
   MN_31_DEC_1990 = 0;   MN_31_DEC_1991 = 0; MN_31_DEC_1992 = 0; MN_31_DEC_1993 = 0;  
   MN_31_DEC_1994 = 0;   MN_31_DEC_1995 = 0; MN_31_DEC_1996 = 0; MN_31_DEC_1997 = 0;    
   MN_31_DEC_1998 = 0;   MN_31_DEC_1999 = 0; MN_31_DEC_2000 = 0; MN_31_DEC_2001 = 0;     
   MN_31_DEC_2002 = 0;   MN_31_DEC_2003 = 0; MN_31_DEC_2004 = 0; MN_31_DEC_2005 = 0;    
   MN_31_DEC_2006 = 0;   MN_31_DEC_2007 = 0; MN_31_DEC_2008 = 0; MN_31_DEC_2009 = 0; 
   MN_31_DEC_2010 = 0;
 
END;                                            
      DO I = AN_DEB_PRE TO AN_FIN_PRE;
 
  SELECT(I);
 
       WHEN(1970) DO;                          
       MN_31_DEC_1970 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1971) DO;                           
       MN_31_DEC_1971 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1972) DO;                           
       MN_31_DEC_1972 + MN_MEN_CAL_PRE;                 
       END;    
 
       WHEN(1973) DO;                          
       MN_31_DEC_1973 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1974) DO;                           
       MN_31_DEC_1974 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1975) DO;                           
       MN_31_DEC_1975 + MN_MEN_CAL_PRE;                 
       END;
 
       WHEN(1976) DO;                          
       MN_31_DEC_1976 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1977) DO;                           
       MN_31_DEC_1977 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1978) DO;                           
       MN_31_DEC_1978 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(1979) DO;                          
       MN_31_DEC_1979 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1980) DO;                           
       MN_31_DEC_1980 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1981) DO;                           
       MN_31_DEC_1981 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(1982) DO;                           
       MN_31_DEC_1982 + MN_MEN_CAL_PRE;                 
       END;    
 
       WHEN(1983) DO;                          
       MN_31_DEC_1983 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1984) DO;                           
       MN_31_DEC_1984 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1985) DO;                           
       MN_31_DEC_1985 + MN_MEN_CAL_PRE;                 
       END;
 
       WHEN(1986) DO;                          
       MN_31_DEC_1986 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1987) DO;                           
       MN_31_DEC_1987 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1988) DO;                           
       MN_31_DEC_1988 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(1989) DO;                          
       MN_31_DEC_1989 + MN_MEN_CAL_PRE;                
       END;  
 
       WHEN(1990) DO;                           
       MN_31_DEC_1990 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1991) DO;                           
       MN_31_DEC_1991 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(1992) DO;                           
       MN_31_DEC_1992 + MN_MEN_CAL_PRE;                 
       END;    
 
       WHEN(1993) DO;                          
       MN_31_DEC_1993 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1994) DO;                           
       MN_31_DEC_1994 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1995) DO;                           
       MN_31_DEC_1995 + MN_MEN_CAL_PRE;                 
       END;
 
       WHEN(1996) DO;                          
       MN_31_DEC_1996 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(1997) DO;                           
       MN_31_DEC_1997 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(1998) DO;                           
       MN_31_DEC_1998 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(1999) DO;                          
       MN_31_DEC_1999 + MN_MEN_CAL_PRE;                
       END; 
 
       WHEN(2000) DO;                           
       MN_31_DEC_2000 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(2001) DO;                           
       MN_31_DEC_2001 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(2002) DO;                           
       MN_31_DEC_2002 + MN_MEN_CAL_PRE;                 
       END;    
 
       WHEN(2003) DO;                          
       MN_31_DEC_2003 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(2004) DO;                           
       MN_31_DEC_2004 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(2005) DO;                           
       MN_31_DEC_2005 + MN_MEN_CAL_PRE;                 
       END;
 
       WHEN(2006) DO;                          
       MN_31_DEC_2006 + MN_MEN_CAL_PRE;                
       END;                                     
 
       WHEN(2007) DO;                           
       MN_31_DEC_2007 + MN_MEN_CAL_PRE;                 
       END;                                     
 
       WHEN(2008) DO;                           
       MN_31_DEC_2008 + MN_MEN_CAL_PRE;                 
       END; 
 
       WHEN(2009) DO;                          
       MN_31_DEC_2009 + MN_MEN_CAL_PRE;                
       END; 
 
       WHEN(2010) DO;                          
       MN_31_DEC_2010 + MN_MEN_CAL_PRE;                
       END; */
 
  END;
END;
 
IF LAST.NO_SEQ_PRE_DEM THEN OUTPUT;
 
RUN;
c'est pas l'ideal d'ou l'objectif d'optimisation !

J'ai tenté ceci:
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
%macro essai (an_debut=, an_fin=, );
 
DATA DATA_essai;
SET DATA1;
 
BY NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM AN_DEB_PRE;
 
	  IF FIRST.NO_SEQ_PRE_DEM THEN DO;
		  %do i= &an_debut. %TO &an_fin. ;
		   MN_31_DEC_&i. = 0; 
		  %end;
 
               END; 
 
      DO I =AN_DEB_PRE TO AN_FIN_PRE;
 	%do i=&an_debut %TO &an_fin; 
	      	SELECT(&i)
                             WHEN(&i) DO;                        
                                MN_31_DEC_&i + MN_MEN_CAL_PRE;                 
		    END;    
		    OTHERWISE; 
		END;
 
	  %end;                                  	  
	END;
 
IF LAST.NO_SEQ_PRE_DEM THEN OUTPUT;
 
RUN;
 
%mend;
options mprint;
%essai (an_debut=1970, an_fin=2010);
La partie avec le SELECT ne retourne pas le resultat escompté car sur chacun de MN_31_DEC_&i il me met la somme de 29+50+50.

Merci d'avance pour vos idées.
MDsas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2011, 08h28   #2
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 828
Points : 2 828
Bonjour.
Outre le fait que je ne suis pas spécialement convaincu qu'une macro s'impose (un ARRAY me semblerait plus simple. Si j'ai un peu de temps dans la journée j'essaierai de faire un petit exemple), dans ton code la boucle macro est mal placée, j'ai l'impression.
Une boucle macro, ce n'est rien d'autre qu'un copier/coller. Si tu regardes dans ton programme initial ce qui est recopié pour chaque année, c'est l'instruction WHEN et elle seule. Pas le SELECT, ni le OTHERWISE, ni le END.
Si tu exécutes ton macro-programme avec l'option MPRINT activée, tu verras dans la log qu'il produit 40 blocs SELECT avec un seul WHEN chacun, au lieu d'un seul bloc SELECT avec 40 WHEN.
Je proposerais donc plutôt
Code :
1
2
3
4
5
6
7
8
9
10
DO I =AN_DEB_PRE TO AN_FIN_PRE;
	      	SELECT(&i)
 	%do i=&an_debut %TO &an_fin; 
                             WHEN(&i) DO;                        
                                MN_31_DEC_&i + MN_MEN_CAL_PRE;                 
		    END;    
        %end;    
		    OTHERWISE; 
		END;                          	  
END;
Bon courage.
Olivier
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/11/2011, 11h25   #3
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 828
Points : 2 828
Voici une solution avec un Array. Pas forcément plus simple à lire mais exempte de macros.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DATA work.test ;
  INPUT NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM MN_MEN_CAL_PRE AN_DEB_PRE AN_FIN_PRE ;
DATALINES ;
1 2 29 1992 1993
1 2 50 1994 1994
1 2 50 2001 2001
;
RUN ;
DATA work.test2 ;
  SET work.test ;
  BY NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM ;
  RETAIN mn_31_dec_1970-mn_31_dec_2010 0 ;
  ARRAY annees mn_31_dec_1970-mn_31_dec_2010 ;
  DO OVER annees ;
    IF AN_DEB_PRE <= INPUT(SCAN(VNAME(annees),4,"_"),4.) <= AN_FIN_PRE THEN annees = MN_MEN_CAL_PRE ;
  END ;
  IF LAST.NO_SEQ_PRE_DEM THEN OUTPUT ;
RUN ;
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/11/2011, 14h34   #4
Membre régulier
 
Femme Mariam
Statisticienne-Consultante BI
Inscription : avril 2008
Messages : 127
Détails du profil
Informations personnelles :
Nom : Femme Mariam
Localisation : Canada

Informations professionnelles :
Activité : Statisticienne-Consultante BI
Secteur : Conseil

Informations forums :
Inscription : avril 2008
Messages : 127
Points : 96
Points : 96
Citation:
Envoyé par olivier.decourt Voir le message
Voici une solution avec un Array. Pas forcément plus simple à lire mais exempte de macros.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DATA work.test ;
  INPUT NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM MN_MEN_CAL_PRE AN_DEB_PRE AN_FIN_PRE ;
DATALINES ;
1 2 29 1992 1993
1 2 50 1994 1994
1 2 50 2001 2001
;
RUN ;
DATA work.test2 ;
  SET work.test ;
  BY NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM ;
  RETAIN mn_31_dec_1970-mn_31_dec_2010 0 ;
  ARRAY annees mn_31_dec_1970-mn_31_dec_2010 ;
  DO OVER annees ;
    IF AN_DEB_PRE <= INPUT(SCAN(VNAME(annees),4,"_"),4.) <= AN_FIN_PRE THEN annees = MN_MEN_CAL_PRE ;
  END ;
  IF LAST.NO_SEQ_PRE_DEM THEN OUTPUT ;
RUN ;
Bonjour,
merci de la réponse. je vais essayer avec la macro car hélas les bornes 1970 et 2010 ne sont pas fixés. Le but est vraiment de pouvoir le généraliser et ne pas être obliger de modifier dans le code des dates.
Merci.
MDsas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2011, 15h25   #5
Membre Expert
 
Avatar de MEGAMIND2
 
Homme Brice Beare
Paris
Inscription : janvier 2011
Messages : 957
Détails du profil
Informations personnelles :
Nom : Homme Brice Beare
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Paris

Informations forums :
Inscription : janvier 2011
Messages : 957
Points : 1 368
Points : 1 368
Bonjour,
Tu peux définir les deux dates en marco-variables, tu n'auras donc pas à modifier le programme que Olivier t'as proposé.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
%let inf=1970;
%let sup=2010;


DATA work.test ;
  INPUT NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM MN_MEN_CAL_PRE AN_DEB_PRE AN_FIN_PRE ;
DATALINES ;
1 2 29 1992 1993
1 2 50 1994 1994
1 2 50 2001 2001
;
RUN ;
DATA work.test2 ;
  SET work.test ;
  BY NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM ;
  RETAIN mn_31_dec_&inf.-mn_31_dec_&sup. 0 ;
  ARRAY annees mn_31_dec_&inf.-mn_31_dec_&sup.;
  DO OVER annees ;
    IF AN_DEB_PRE <= INPUT(SCAN(VNAME(annees),4,"_"),4.) <= AN_FIN_PRE THEN annees = MN_MEN_CAL_PRE ;
  END ;
  IF LAST.NO_SEQ_PRE_DEM THEN OUTPUT ;
RUN ;
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/11/2011, 15h59   #6
Membre régulier
 
Femme Mariam
Statisticienne-Consultante BI
Inscription : avril 2008
Messages : 127
Détails du profil
Informations personnelles :
Nom : Femme Mariam
Localisation : Canada

Informations professionnelles :
Activité : Statisticienne-Consultante BI
Secteur : Conseil

Informations forums :
Inscription : avril 2008
Messages : 127
Points : 96
Points : 96
Citation:
Envoyé par MEGAMIND2 Voir le message
Bonjour,
Tu peux définir les deux dates en marco-variables, tu n'auras donc pas à modifier le programme que Olivier t'as proposé.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
%let inf=1970;
%let sup=2010;


DATA work.test ;
  INPUT NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM MN_MEN_CAL_PRE AN_DEB_PRE AN_FIN_PRE ;
DATALINES ;
1 2 29 1992 1993
1 2 50 1994 1994
1 2 50 2001 2001
;
RUN ;
DATA work.test2 ;
  SET work.test ;
  BY NO_SEQ_CLI_BEN NO_SEQ_PRE_DEM ;
  RETAIN mn_31_dec_&inf.-mn_31_dec_&sup. 0 ;
  ARRAY annees mn_31_dec_&inf.-mn_31_dec_&sup.;
  DO OVER annees ;
    IF AN_DEB_PRE <= INPUT(SCAN(VNAME(annees),4,"_"),4.) <= AN_FIN_PRE THEN annees = MN_MEN_CAL_PRE ;
  END ;
  IF LAST.NO_SEQ_PRE_DEM THEN OUTPUT ;
RUN ;
J'avais pensé à cette solution après avoir répondu.
J'ai résolu mon problème merci de vos contributions. Je garde la solution des Arrays dans un coin pour un besoin futur. Pour etre honnete je suis pas très a l'aise avec car je comprend pas comment ca marche en realité
Mais cela peut servir !!!
MDsas est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/11/2011, 17h09   #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 : 142
Points : 142
Bonjour,

Concernant les ARRAY, j'ai écrit un article en français à ce sujet : http://www.sas.com/offices/europe/fr...support_13.pdf
Cet un outil très interessant, j'espère que l'article vous aidera à vous familiariser avec.

Géraldine Cade Deschamps
Support Clients SAS
Géraldine_Cade_SAS est déconnecté   Envoyer un message privé Réponse avec citation 30
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 13h53.


 
 
 
 
Partenaires

Hébergement Web