Les posteurs les plus actifs de la semaine
Aucun utilisateur |
Sujets les plus vus
Simplification de code ? (boucle, macro)
2 participants
Page 1 sur 1
Simplification de code ? (boucle, macro)
Bonjour,
Je cherche un moyen d'obtenir plusieurs valeurs en fonction d'autres, ce pour 2 cas distincts.
VARA : Supposons que ma varA est 1704, sous - entendu le mois d'avril 2017. J'aimerais trouver un moyen d'obtenir ces mêmes valeurs pour les 5 mois précédents. C'est à dire les valeurs : 1703, 1702, 1701, 1612, 1611.
VARB : Supposons que ma varB est 03, je cherche à obtenir les 5 valeurs précédentes sachant qu'elles vont de 01 à 13, c'est à dire les valeurs : 02, 01, 13, 12, 11.
YEAR : Celle - ci est liée à varB, supposons qu'elle soit égal à 2017, je cherche à diminuer d'une année si et seulement si, ma varB est égale à 13, c'est à dire les valeurs 2017, 2017, 2016, 2016, 2016.
Et ainsi pouvoir intégrer ces valeurs directement dans mes créations de table.
J'ai quelques idées de comment m'y prendre, notamment en décomposant ce chiffre en deux parties et à jouer avec les boucles, mais la solution que j'ai écrite semble pouvoir être optimisée.
Je n'ai pas l'impression d'être clair ... mais en tout les cas, le code fonctionne.
Mac_Leod.
Je cherche un moyen d'obtenir plusieurs valeurs en fonction d'autres, ce pour 2 cas distincts.
VARA : Supposons que ma varA est 1704, sous - entendu le mois d'avril 2017. J'aimerais trouver un moyen d'obtenir ces mêmes valeurs pour les 5 mois précédents. C'est à dire les valeurs : 1703, 1702, 1701, 1612, 1611.
VARB : Supposons que ma varB est 03, je cherche à obtenir les 5 valeurs précédentes sachant qu'elles vont de 01 à 13, c'est à dire les valeurs : 02, 01, 13, 12, 11.
YEAR : Celle - ci est liée à varB, supposons qu'elle soit égal à 2017, je cherche à diminuer d'une année si et seulement si, ma varB est égale à 13, c'est à dire les valeurs 2017, 2017, 2016, 2016, 2016.
Et ainsi pouvoir intégrer ces valeurs directement dans mes créations de table.
- Code:
Exemple :
data want;
set tab_1611
tab_1612
tab_1701
tab_1702
tab_1703;
run;
J'ai quelques idées de comment m'y prendre, notamment en décomposant ce chiffre en deux parties et à jouer avec les boucles, mais la solution que j'ai écrite semble pouvoir être optimisée.
- Code:
%macro _suivi_periode(varA, varB);
%if %substr(&varA.,3,2) ne 01 %then %do; %let varA1 = %eval(&varA.-1); %end;
%else %if %substr(&varA.,3,2) eq 01 %then %do; %let varA1 = %eval(%substr(&varA.,1,2)-1)12; %end;
%if %substr(&varA1.,3,2) ne 01 %then %do; %let varA2 = %eval(&varA1.-1); %end;
%else %if %substr(&varA1.,3,2) eq 01 %then %do; %let varA2 = %eval(%substr(&varA1.,1,2)-1)12; %end;
%if %substr(&varA2.,3,2) ne 01 %then %do; %let varA3 = %eval(&varA2.-1); %end;
%else %if %substr(&varA2.,3,2) eq 01 %then %do; %let varA3 = %eval(%substr(&varA2.,1,2)-1)12; %end;
%if %substr(&varA3.,3,2) ne 01 %then %do; %let varA4 = %eval(&varA3.-1); %end;
%else %if %substr(&varA3.,3,2) eq 01 %then %do; %let varA4 = %eval(%substr(&varA3.,1,2)-1)12; %end;
%if %substr(&varA4.,3,2) ne 01 %then %do; %let varA5 = %eval(&varA4.-1); %end;
%else %if %substr(&varA4.,3,2) eq 01 %then %do; %let varA5 = %eval(%substr(&varA4.,1,2)-1)12; %end;
%let year = 20%substr(&varA., 1, 2);
%if &varB. ne 01 %then %do; %let varB1 = %sysfunc(putn(%eval(&varB.-1), z2.)); %let year1 = &year.; %end;
%else %if &varB. eq 01 %then %do; %let varB1 = 13; %let year1 = %eval(&year.-1); %end;
%if &varB1. ne 01 %then %do; %let varB2 = %sysfunc(putn(%eval(&varB1.-1), z2.)); %let year2 = &year1.; %end;
%else %if &varB1. eq 01 %then %do; %let varB2 = 13; %let year2 = %eval(&year1.-1); %end;
%if &varB2. ne 01 %then %do; %let varB3 = %sysfunc(putn(%eval(&varB2.-1), z2.)); %let year3 = &year2.; %end;
%else %if &varB2. eq 01 %then %do; %let varB3 = 13; %let year3 = %eval(&year2.-1); %end;
%if &varB3. ne 01 %then %do; %let varB4 = %sysfunc(putn(%eval(&varB3.-1), z2.)); %let year4 = &year3.; %end;
%else %if &varB3. eq 01 %then %do; %let varB4 = 13; %let year4 = %eval(&year3.-1); %end;
%if &varB4. ne 01 %then %do; %let varB5 = %sysfunc(putn(%eval(&varB4.-1), z2.)); %let year5 = &year4.; %end;
%else %if &varB4. eq 01 %then %do; %let varB5 = 13; %let year5 = %eval(&year4.-1); %end;
%mend _suivi_periode;
%_suivi_periode(1704, 04);
Je n'ai pas l'impression d'être clair ... mais en tout les cas, le code fonctionne.
Mac_Leod.
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Re: Simplification de code ? (boucle, macro)
Bonjour,
voilà ce que j'ai fait.
Je te laisse t'approprier le code et me dire si ça te convient ou pas :-) :
Niaboc
voilà ce que j'ai fait.
Je te laisse t'approprier le code et me dire si ça te convient ou pas :-) :
- Code:
/*création de la table de test*/
data a;
input id varA varB $;
cards;
1 1704 04
2 1505 05
;
run;
/*on crée la variable année et une variable temporaire*/
data a;
set a;
year=2000+int(varA/100);
temp=(year||varB)*1;
run;
%macro test;
/*pour l'append*/
proc delete data=b;
run;
/*liste de 1 à 13 et de 1 à 12*/
%let list_per=;
%let list_per2=;
%do i=1 %to 13;
%let list_per=&i &list_per;
%if &i<13 %then %do;
%let list_per2=&i &list_per2;
%end;
%end;
%do i=0 %to 5;
data a&i;
set a;
/*si le numéro de période n'est plus dans 1 à 13 alors on passe à la 13ème période de l'année précédente*/
if substr(temp-&i,11,2)*1 not in (&list_per) then do;
temp=temp-&i-100+13;
end;
else do;
temp=temp-&i;
end;
/*si le numéro de mois n'est plus dans 1 à 13 alors on passe à la 13ème période de l'année précédente*/
if substr(varA-&i,11,2)*1 not in (&list_per2) then do;
varA=varA-&i-100+12;
end;
else do;
varA=varA-&i;
end;
run;
/*on se recalcule les variables varB et year en fonction de temp*/
data a&i;
set a&i;
varB=substr(temp,11,2);
year=substr(temp,7,4);
run;
/*on append dans la table de résultats*/
proc append data=a&i base=b;
run;
/*on supprime les tables intermédiaires*/
proc delete data=a&i;
run;
%end;
/*on supprime la variable temporaire dans les deux tables*/
data a;
set a;
drop temp;
run;
proc sort data=b (drop=temp);
by id;
run;
%mend test;
%test;
Niaboc
niaboc- Nombre de messages : 1001
Age : 37
Localisation : Paris
Date d'inscription : 05/05/2008
Re: Simplification de code ? (boucle, macro)
Je suis en train d'y jeter un oeil et essaye de le comprendre.
J'avoue ne pas comprendre le pourquoi de cette formule :
La variable temp n'a t-elle pas que 6 chiffres ? Comment peut -on dans ce cas récupérer les 11 et 12ème chiffres ?
J'avoue ne pas comprendre le pourquoi de cette formule :
- Code:
if substr(temp-&i,11,2)*1
La variable temp n'a t-elle pas que 6 chiffres ? Comment peut -on dans ce cas récupérer les 11 et 12ème chiffres ?
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Re: Simplification de code ? (boucle, macro)
La variable n'a que 6 chiffres mais le format est best12.
Le substr travaillant sur des caractères, le chiffre est pris comme un caractère. Comme il est incrémenté à droite, il y a 6 espaces vides devant. Et on veut donc récupérer 2 chiffres à partir du 11ème...
Pour être plus propre voici ce que tu peux faire :
où j'ai remplacé les
pour transformer la variable numérique en caractère sur 6 positions.
En espérant avoir été clair!
Niaboc
Le substr travaillant sur des caractères, le chiffre est pris comme un caractère. Comme il est incrémenté à droite, il y a 6 espaces vides devant. Et on veut donc récupérer 2 chiffres à partir du 11ème...
Pour être plus propre voici ce que tu peux faire :
- Code:
/*création de la table de test*/
data a;
input id varA varB $;
cards;
1 1704 04
2 1505 05
;
run;
%macro test;
/*on crée la variable année et une variable temporaire*/
data a;
set a;
year=2000+int(varA/100);
temp=(year||varB)*1;
run;
/*pour l'append*/
proc delete data=b;
run;
/*liste de 1 à 13 et de 1 à 12*/
%let list_per=;
%let list_per2=;
%do i=1 %to 13;
%let list_per=&i &list_per;
%if &i<13 %then %do;
%let list_per2=&i &list_per2;
%end;
%end;
%do i=0 %to 5;
data a&i;
set a;
/*si le numéro de période n'est plus dans 1 à 13 alors on passe à la 13ème période de l'année précédente*/
if substr(put(temp-&i,6.),5,2)*1 not in (&list_per) then do;
temp=temp-&i-100+13;
end;
else do;
temp=temp-&i;
end;
/*si le numéro de mois n'est plus dans 1 à 13 alors on passe à la 13ème période de l'année précédente*/
if substr(put(varA-&i,4.),3,2)*1 not in (&list_per2) then do;
varA=varA-&i-100+12;
end;
else do;
varA=varA-&i;
end;
run;
/*on se recalcule les variables varB et year en fonction de temp*/
data a&i;
set a&i;
varB=substr(put(temp,6.),5,2);
year=substr(put(temp,6.),1,4);
run;
/*on append dans la table de résultats*/
proc append data=a&i base=b;
run;
/*on supprime les tables intermédiaires*/
proc delete data=a&i;
run;
%end;
/*on supprime la variable temporaire dans les deux tables*/
data a;
set a;
drop temp;
run;
proc sort data=b (drop=temp);
by id;
run;
%mend test;
%test;
où j'ai remplacé les
- Code:
if substr(temp-&i,11,2)*1
- Code:
if substr(put(temp-&i,6.),5,2)*1
pour transformer la variable numérique en caractère sur 6 positions.
En espérant avoir été clair!
Niaboc
niaboc- Nombre de messages : 1001
Age : 37
Localisation : Paris
Date d'inscription : 05/05/2008
Re: Simplification de code ? (boucle, macro)
Merci, c'est parfaitement clair ! Par souci de compréhension pour d'autres, j'utiliserais cette formule qui offre le format attendu.
Une autre question, y a t-il un moyen de macrotiser ce bout de code en ne spécifiant dans la macro que les varA, et varB ? La création des tables via un cards empêche l'utilisation de toute macro ...
Une autre question, y a t-il un moyen de macrotiser ce bout de code en ne spécifiant dans la macro que les varA, et varB ? La création des tables via un cards empêche l'utilisation de toute macro ...
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Re: Simplification de code ? (boucle, macro)
Oui il y a moyen, mais en sortie tu veux quoi du coup?
Une table comme j'ai fait ou les lignes sont démultipliées avec les 5 dates précédentes, ou tu les voudrais en colonne?
Une table comme j'ai fait ou les lignes sont démultipliées avec les 5 dates précédentes, ou tu les voudrais en colonne?
niaboc- Nombre de messages : 1001
Age : 37
Localisation : Paris
Date d'inscription : 05/05/2008
Re: Simplification de code ? (boucle, macro)
Je ne saurais trop m'avancer là dessus.
Je me demande de quelle façon, je vais pouvoir réutiliser ces données dans mes créations de tables à vrai dire. Initialement, chaque valeur était rattaché à une macro à l'aide d'un %let, ce qui me permettait de chacune les appeler.
Du coup, avoir une sortie en ligne ou en colonne, je ne m'imagine pas encore comment je vais pouvoir les récupérer.
Je me demande de quelle façon, je vais pouvoir réutiliser ces données dans mes créations de tables à vrai dire. Initialement, chaque valeur était rattaché à une macro à l'aide d'un %let, ce qui me permettait de chacune les appeler.
Du coup, avoir une sortie en ligne ou en colonne, je ne m'imagine pas encore comment je vais pouvoir les récupérer.
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Re: Simplification de code ? (boucle, macro)
on peut s'arranger pour les remettre dans une macro-variable j'imagine. Je regarde ça!
niaboc- Nombre de messages : 1001
Age : 37
Localisation : Paris
Date d'inscription : 05/05/2008
Re: Simplification de code ? (boucle, macro)
Merci pour ce temps que tu m'accordes !
Pour info, je ne cherche qu'à utiliser ces valeurs selon le nom de mes tables. Comme dans l'exemple plus haut, cela ressemblerais à ça :
Ou bien une simple proc sort dont les conditions sont les valeurs que j'essaye de récupérer.
Pour info, je ne cherche qu'à utiliser ces valeurs selon le nom de mes tables. Comme dans l'exemple plus haut, cela ressemblerais à ça :
- Code:
data want;
set tab_1611
tab_1612
tab_1701
tab_1702
tab_1703;
run;
Ou bien une simple proc sort dont les conditions sont les valeurs que j'essaye de récupérer.
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Re: Simplification de code ? (boucle, macro)
J'ai écrit ça, qu'à partir de macro-variable du coup.
Le programme créée donc 5 nouvelles macro-variables par variable :
varA1, ---, varA5
varB1, ---, varB5
year1, ---, year5.
ça te va?
Le programme créée donc 5 nouvelles macro-variables par variable :
varA1, ---, varA5
varB1, ---, varB5
year1, ---, year5.
- Code:
%macro test(varA, varB);
options minoperator;
/*on crée la variable année et une variable temporaire*/
%let year=%sysevalf(2000+%sysfunc(int(&varA/100)));
%let temp=&year&varB;
%put ;
%put la valeur de varA est : &varA..;
%put la valeur de varB est : &varB..;
%put la valeur de year est : &year..;
%put ;
/*liste de 1 à 13 et de 1 à 12*/
%let list_per=;
%let list_per2=;
%do i=1 %to 13;
%let list_per=&list_per &i;
%if &i<13 %then %do;
%let list_per2=&list_per2 &i;
%end;
%end;
%do i=1 %to 5;
/*si le numéro de période n'est plus dans 1 à 13 alors on passe à la 13ème période de l'année précédente*/
%if not(%eval(%substr(%eval(&varA-&i),3,2)*1) in &list_per2) %then %do;
%let varA&i=%eval(&varA-&i-100+12);
%end;
%else %do;
%let varA&i=%eval(&varA-&i);
%end;
/*si le numéro de période n'est plus dans 1 à 13 alors on passe à la 13ème période de l'année précédente*/
%if not(%eval(%substr(%eval(&temp-&i),5,2)*1) in &list_per) %then %do;
%let temp&i=%eval(&temp-&i-100+13);
%end;
%else %do;
%let temp&i=%eval(&temp-&i);
%end;
%let varB&i=%substr(&&temp&i,5,2);
%let year&i=%substr(&&temp&i,1,4);
%put valeur du décalage : &i..;
%put la valeur de varA&i est : &&varA&i...;
%put la valeur de varB&i est : &&varB&i...;
%put la valeur de year&i est : &&year&i...;
%put ;
%end;
%mend test;
%test(1704,04);
%test(1505,05);
ça te va?
niaboc- Nombre de messages : 1001
Age : 37
Localisation : Paris
Date d'inscription : 05/05/2008
Re: Simplification de code ? (boucle, macro)
En dehors de l'adaptation que j'ai dû en faire pour que cela concorde avec mes données, le programme est parfaitement parfait. C'est exactement ce dont j'avais besoin ! Merci à toi !
Je me permet tout de même une petite question. Quelle modif' apporte l'options minoperator à l’exécution du programme ? Est - ce lié à l'utilisation des "IN" pour les listes ?
Je me permet tout de même une petite question. Quelle modif' apporte l'options minoperator à l’exécution du programme ? Est - ce lié à l'utilisation des "IN" pour les listes ?
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Re: Simplification de code ? (boucle, macro)
l'option minoperator permet effectivement de lire l'opérateur "IN" dans un "%IF".
Par défaut SAS ne le comprend pas.
Par défaut SAS ne le comprend pas.
niaboc- Nombre de messages : 1001
Age : 37
Localisation : Paris
Date d'inscription : 05/05/2008
Re: Simplification de code ? (boucle, macro)
Parfait dans ce cas.
Je découvre certaines fonctions, du moins, leur utilisation et je te remercie encore une fois pour m'avoir accordé une bonne partie de ton temps.
Je découvre certaines fonctions, du moins, leur utilisation et je te remercie encore une fois pour m'avoir accordé une bonne partie de ton temps.
Mac_Leod- Nombre de messages : 28
Date d'inscription : 25/06/2015
Sujets similaires
» Macro et liste de variable
» Macro Excel: tests statistiques
» Boucle d'histogramme
» Equivalent dans une boucle ?
» calcul avec boucle
» Macro Excel: tests statistiques
» Boucle d'histogramme
» Equivalent dans une boucle ?
» calcul avec boucle
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|