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/03/2011, 09h05   #1
Invité régulier
 
Homme Xavier
Chargé d'Etudes Statistiques
Inscription : février 2009
Messages : 39
Détails du profil
Informations personnelles :
Nom : Homme Xavier
Localisation : France

Informations professionnelles :
Activité : Chargé d'Etudes Statistiques

Informations forums :
Inscription : février 2009
Messages : 39
Points : 7
Points : 7
Par défaut Renommer des variables avec une macro SAS

Bonjour,

Je souhaite renommer des variables dans une table.

J'ai une table avec 46 variables toutes nommées ainsi :
Arbo_1
Arbo_2
Arbo_3
...etc...

J'ai une table de référence WORK.VAR_ARBO avec ces indicateurs : NUM / NOM

Par exemple :
NUM / NOM
1 / LIVRES
2 / BD
3 / DVD

Je voudrais que les variables de ma table de départ passent de :
Arbo_1 à LIVRES
Arbo_2 à BD
Arbo_3 à DVD

Le NUM correspond au chiffre associé à Arbo_i...

Avez vous une solution efficace ?

Merci par avance !
zellinho est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 09h15   #2
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 701
Points : 1 701
Bonjour;

si tu veux renommer tes variables avec des espaces , saches que c'est impossible sous sas (Arbo_1 à LIVRES) et les caractères accentués non supporté.
veux tu un résultat comme suite : Arbo_1_a_LIVRES?
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 09h19   #3
Invité régulier
 
Homme Xavier
Chargé d'Etudes Statistiques
Inscription : février 2009
Messages : 39
Détails du profil
Informations personnelles :
Nom : Homme Xavier
Localisation : France

Informations professionnelles :
Activité : Chargé d'Etudes Statistiques

Informations forums :
Inscription : février 2009
Messages : 39
Points : 7
Points : 7
Je me suis un peu mal exprimé...

les variables de ma table de départ sont :
Arbo_1
Arbo_2
Arbo_3

et je souhaite que ma table de sortie soit avec les variables renommées ainsi :
LIVRES
BD
DVD

Merci
zellinho est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 09h25   #4
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Bonjour,

voici une première version à améliorer.
penser à vérifier que le nombre de valeurs dans le referentiel est égale au nombre de variables dans la table...
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
 
DATA VAR_ARBO ;
length num 3 nom $10;
input num nom $;
cards;
1 livres
2 bd
3 dvd
;
run;
DATA _null_;SET VAR_ARBO ;
call symput('var'||LEFT(trim(num)),nom);
call symput('nb',_n_);
run;
%put _user_;
proc sql;
CREATE TABLE resu  (arbo_1 char(2),arbo_2 char(2),arbo_3 char(2));
quit;;
%macro RENAME;
proc datasets lib=work;
MODIFY resu ;
RENAME 
%do i=1 %TO &nb;
	arbo_&i=&&var&i
%end;;
quit;
%mend;
%RENAME;
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/03/2011, 09h30   #5
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
ce que je ferais , c'est créer une table ou chaque ligne fait corresponde les éléments que tu veux associer.

ex:ligne 1, colonne 1:Arbo_1
ligne 1 , colonne 2: LIVRES

A partir de la je créerais une nouvelle colonne, qui spécifierait sous forme d'une chaine de caractère le rename:


ligne 1 , colonne 3: Arbo_1=LIVRES.

ensuite par une proc sql tu peux sélectionner tes 46 lignes et stocker dans une macro:
Code :
1
2
3
4
5
 
proc sql;
SELECT DISTINCT colonne3 INTO :macrlist separated BY " "
FROM file
;quit;
puis utiliser la macro variable dans le rename. Attention à la longueur de la macro variable toutefois, bien vérifier que la fin n'a pas été coupée
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 09h37   #6
Invité régulier
 
Homme Xavier
Chargé d'Etudes Statistiques
Inscription : février 2009
Messages : 39
Détails du profil
Informations personnelles :
Nom : Homme Xavier
Localisation : France

Informations professionnelles :
Activité : Chargé d'Etudes Statistiques

Informations forums :
Inscription : février 2009
Messages : 39
Points : 7
Points : 7
SUPER !

Merci, c'est parfait, c'est exactement ce que je voulais avoir !
zellinho est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 10h06   #7
Membre Expert
 
Avatar de MEGAMIND2
 
Homme Brice Beare
Paris
Inscription : janvier 2011
Messages : 956
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 : 956
Points : 1 366
Points : 1 366
Citation:
Envoyé par zellinho Voir le message
SUPER !

Merci, c'est parfait, c'est exactement ce que je voulais avoir !
Bonjour,
Ce que j'aurais fait moi pour automatiser complétement le travail

Code :
1
2
3
4
5
6
7
8
9
10
11
12
DATA initial;
input arbo_1 $ arbo_2 $ arbo_3 $;
datalines;
1 2 3
;
run;
DATA bd;
input LIVRE$ BD $ DVD$;
datalines;
4 5 6
;
run;
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
/* cette macro renomme les variables de la table initiale par les variables 
   de la table pivo
 **> il faut s'assurer qu'on a les mêmes nombre de variables dans les deux tables*/
 
macro M(table_initial= , table_pivo=);
 
	proc contents DATA=&table_initial out=out1(keep=NAME VARNUM);
	run;
	proc contents DATA=&table_pivo out=out2(keep=NAME VARNUM);
	run;
	proc sort DATA=out1;BY VARNUM;RUN;
	proc sort DATA=out2;BY VARNUM;RUN;
	proc sql;
	SELECT name INTO: l1 separated BY ' ' FROM out1;
	SELECT count(*) INTO:nb FROM out1;
	SELECT name INTO: l2 separated BY ' ' FROM out2;
	quit;
	%put &l1;
	%put &l2;
	DATA &table_initial;
	SET &table_initial;
	%do i=1 %TO &NB.;
		%let l1&i=%scan(&l1.,&i,' ');
		%let l2&i=%scan(&l2.,&i,' ');
		RENAME &&l1&i=&&l2&i;
	%end;
	run;
%mend;
%M(table_initial=initial , table_pivo=bd);
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 10h14   #8
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Lire une table juste pour renommer les variables n'est pas une solution optimisée....
Elle nécessite la lecture et l'écriture de la table.
Alors qu'avec une proc datasets ou une proc sql (alter table), on travail directement sur le descripteur du fichier.
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 10h26   #9
Membre Expert
 
Avatar de MEGAMIND2
 
Homme Brice Beare
Paris
Inscription : janvier 2011
Messages : 956
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 : 956
Points : 1 366
Points : 1 366
Citation:
Envoyé par bahraoui Voir le message
Lire une table juste pour renommer les variables n'est pas une solution optimisée....
Elle nécessite la lecture et l'écriture de la table.
Alors qu'avec une proc datasets ou une proc sql (alter table), on travail directement sur le descripteur du fichier.
Tu as raison barahoui, j'ai changé mon étape data par une proc datatests

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
 
/* cette macro renomme les variables de la table initiale par les variables 
   de la table pivo
 **> il faut s'assurer qu'on a les mêmes nombre de variables dans les deux tables*/
%macro M(table_initial= , table_pivo=);
 
	proc contents DATA=&table_initial out=out1(keep=NAME VARNUM);
	run;
	proc contents DATA=&table_pivo out=out2(keep=NAME VARNUM);
	run;
	proc sort DATA=out1;BY VARNUM;RUN;
	proc sort DATA=out2;BY VARNUM;RUN;
	proc sql;
	SELECT name INTO: l1 separated BY ' ' FROM out1;
	SELECT count(*) INTO:nb FROM out1;
	SELECT name INTO: l2 separated BY ' ' FROM out2;
	quit;
	%put &l1;
	%put &l2;
	 proc datasets lib=work;
     MODIFY &table_initial ;
       %do i=1 %TO &NB.;
		%let l1&i=%scan(&l1.,&i,' ');
		%let l2&i=%scan(&l2.,&i,' ');
		RENAME &&l1&i=&&l2&i;
 
%end;;
	run;
	quit;
%mend;
%M(table_initial=initial , table_pivo=bd);
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 10h46   #10
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
Il y encore plus simple je pense. Tout peut se faire en une sql, pas besoin de boucler.

Code :
1
2
3
4
5
 
proc sql;
SELECT DISTINCT colonne1||"="||colonne2 INTO :macrlist separated BY " "
FROM file
;quit;
si colonne1 et colonne 2 se trouvent dans deux fichiers différents on peut joindre dans le from du sql.

Puis modifier le nom de variable via un rename en entrée dans l'étape/procédure suivante.
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 11h08   #11
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Citation:
Envoyé par MEGAMIND2 Voir le message
Tu as raison barahoui, j'ai changé mon étape data par une proc datatests

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
 
/* cette macro renomme les variables de la table initiale par les variables 
   de la table pivo
 **> il faut s'assurer qu'on a les mêmes nombre de variables dans les deux tables*/
%macro M(table_initial= , table_pivo=);
 
	proc contents DATA=&table_initial out=out1(keep=NAME VARNUM);
	run;
	proc contents DATA=&table_pivo out=out2(keep=NAME VARNUM);
	run;
	proc sort DATA=out1;BY VARNUM;RUN;
	proc sort DATA=out2;BY VARNUM;RUN;
	proc sql;
	SELECT name INTO: l1 separated BY ' ' FROM out1;
	SELECT count(*) INTO:nb FROM out1;
	SELECT name INTO: l2 separated BY ' ' FROM out2;
	quit;
	%put &l1;
	%put &l2;
	 proc datasets lib=work;
     MODIFY &table_initial ;
       %do i=1 %TO &NB.;
		%let l1&i=%scan(&l1.,&i,' ');
		%let l2&i=%scan(&l2.,&i,' ');
		RENAME &&l1&i=&&l2&i;
 
%end;;
	run;
	quit;
%mend;
%M(table_initial=initial , table_pivo=bd);
Je viens de relire ton code et je constate que tu ne réponds pas exactement à la demande.
Les nouvelles variables se trouve dans une variable d'une table.
Code :
1
2
3
4
5
6
7
8
 
J'ai une table de référence WORK.VAR_ARBO avec ces indicateurs : NUM / NOM
 
Par exemple :
NUM / NOM
1 / LIVRES
2 / BD
3 / DVD
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 11h24   #12
Membre Expert
 
Avatar de MEGAMIND2
 
Homme Brice Beare
Paris
Inscription : janvier 2011
Messages : 956
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 : 956
Points : 1 366
Points : 1 366
Citation:
Envoyé par bahraoui Voir le message
Je viens de relire ton code et je constate que tu ne réponds pas exactement à la demande.
Les nouvelles variables se trouve dans une variable d'une table.
Code :
1
2
3
4
5
6
7
8
 
J'ai une table de référence WORK.VAR_ARBO avec ces indicateurs : NUM / NOM
 
Par exemple :
NUM / NOM
1 / LIVRES
2 / BD
3 / DVD
Il suffit juste de supprimer la proc contents en trop et remplacer par:

Code :
1
2
3
proc sql;
	SELECT NOM INTO: l1 separated BY ' ' FROM WORK.VAR_ARBO ;
quit;
Non barahoui? pour moi il a 0 pb
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 11h26   #13
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
comme ça c'est mieux, la solution répond au besoins du client
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 11h37   #14
Membre Expert
 
Avatar de MEGAMIND2
 
Homme Brice Beare
Paris
Inscription : janvier 2011
Messages : 956
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 : 956
Points : 1 366
Points : 1 366
Citation:
Envoyé par bahraoui Voir le message
comme ça c'est mieux, la solution répond au besoins du client
Le client est roi
Sinon c'est bien de voir différentes approches de chacun (de toi et Manoutz) pour aller à Rôme.
ça m'a permit aussi d'optimiser mon code.
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2011, 11h42   #15
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
Citation:
Envoyé par MEGAMIND2 Voir le message
Le client est roi
Sinon c'est bien de voir différentes approches de chacun (de toi et Manoutz) pour aller à Rôme.
ça m'a permit aussi d'optimiser mon code.
Peut mieux faire!

Voici comment tout gérer en une proc sql

Code :
1
2
3
4
5
6
7
8
9
10
11
proc sql;
	SELECT DISTINCT compress(A.nameorigin)||"="||B.Varname INTO :macrlist separated BY " "
	FROM INIT AS A INNER JOIN
		(SELECT DISTINCT name AS varname, monotonic() AS nb 
		FROM sashelp.vcolumn
		WHERE libname IN ('SASHELP') AND memname IN ('CARS')) AS B
	ON A.nb=B.nb
;
quit;
 
%put &macrlist.;
j'ai au préalable créé le fichier init, ou chaque correspond au nommage d'une variable d'une fichier source. Init est déjà à la disposition de zelinho.

proc contents et datasets sont inutiles (enfin, non optimales). Reste plus renommer au début de l'étape suivante (c'est même peut être gérable au sein de la sql via un alter table ou un modify...)
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/03/2011, 17h57   #16
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,

Cette problématique est un excellent candidat pour le CALL EXECUTE ! Surtout si l'on ne connait pas le macro-langage. Le tour est joué en 6 lignes de code.

Pour ma part je propose donc 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
DATA initial;
input arbo_1 $ arbo_2 $ arbo_3 $;
datalines;
1 2 3
;
DATA VAR_ARBO ;
length num 3 nom $10;
input num nom $;
cards;
1 livres
2 bd
3 dvd
;
run;
 
DATA _null_ ;
  SET VAR_ARBO end=last;
  IF _n_=1 then   call execute ("proc datasets lib=work ;  modify initial ;    rename ") ;
 
  call execute ( compress("arbo_" !! num) !! " = " !! nom) ;
 
  IF last then call execute (";quit;") ;
  run ;
CALL EXECUTE permet d'écrire le code qui sera exécuté une fois l'étape DATA en cours terminée. Ainsi on écrit du code en fonction du contenu d'une table.
J'ai écrit un article à ce sujet il y a quelques années si quelqu'un souhaite aller plus loin :
http://www.sas.com/offices/europe/fr...port_14_bd.pdf

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



Fuseau horaire GMT +2. Il est actuellement 19h40.


 
 
 
 
Partenaires

Hébergement Web