Précédent   Forum des professionnels en informatique > Logiciels > Solutions d'entreprise > Business Intelligence > SAS > Débutez
Débutez Forum concentrant les premières questions que l'on se pose en tant que débutant
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/12/2010, 11h23   #1
Membre habitué
 
Homme
Consultant informatique
Inscription : mars 2002
Messages : 211
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Belgique

Informations professionnelles :
Activité : Consultant informatique

Informations forums :
Inscription : mars 2002
Messages : 211
Points : 133
Points : 133
Par défaut proc TRANSPOSE avec 2 tables

Bonjour,

Quelqu'un peut-il m'aider avec le problème suivant?

J'ai 2 tables: Client et Contrats qui sont liées par l'id du Client (idcl)
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DATA client1;
	length idcl $3. client $8.;
	input idcl client;
datalines;
001 Bernard
002 Laurent
003 Fabian
;
run;
 
DATA contrat2;
	length idct $3. nom $5. idcl $3. am 3.;
	input idct nom idcl am;
datalines;
101 AAAAA 001 150
102 BBBBB 001 200
103 CCCCC 003 500
;
run;

Le but est d'obtenir une table finale avec à chaque fois une ligne qui contient:
Le client et tous ses contrats les unes à la suite des autres (ainsi que les infos du contrat).

J'ai essayé avec un proc transpose mais je n'y arrive pas puisque je suis avec 2 table et des données en plus.

Ci dessous une exemple du code que j'ai essayé:
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
DATA client1;
	length idcl $3. client $8.;
	input idcl client;
datalines;
001 Bernard
002 Laurent
003 Fabian
;
run;
 
DATA contrat2;
	length idct $3. nom $5. idcl $3. am 3.;
	input idct nom idcl am;
datalines;
101 AAAAA 001 150
102 BBBBB 001 200
103 CCCCC 003 500
;
run;
 
proc sort DATA=client1 out= client;
	BY idcl;
run;
 
proc sort DATA=contrat2 out= contrat;
	BY idcl;
run;
 
DATA test;
	merge client (IN = InCl)
 		contrat (IN= InCt);
	BY idcl;
 
	IF InCl AND InCt;
run;
 
proc sort DATA=test;
	BY client;
run;
 
proc transpose DATA=test out=pivot;
	BY client;
	var nom;
run;
J'obtiens bien une table avec:
ligne1: Bernard AAA BBB
ligne2: Fabian CCC

mais je n'arrive pas à mettre les données supplémentaires du contrat, par exemple son montant (am)

Quelqu'un peut-il m'aider?

Ou existe-t-il une meilleure solution que TRANSPOSE?

Merci
L0007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/12/2010, 12h47   #2
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
la solution via une transpose est une option envisageable, il est plus simple dans ce cas que tu transpose en premier ta table contrat2 de sorte à obtenir une ligne par idcl. Forme ensuite une table finale en joignant tes deux table (à identifiant unique), comme tu l'as fait par un data step par exemple
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/12/2010, 13h57   #3
Membre habitué
 
Homme
Consultant informatique
Inscription : mars 2002
Messages : 211
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Belgique

Informations professionnelles :
Activité : Consultant informatique

Informations forums :
Inscription : mars 2002
Messages : 211
Points : 133
Points : 133
Citation:
il est plus simple dans ce cas que tu transpose en premier ta table contrat2 de sorte à obtenir une ligne par idcl
Ok, je pense que mon problème se situe plus spécifiquement ici.
Quand je fais:
Code :
1
2
3
4
proc transpose DATA=contrat out=pivot2;
	BY idcl;
	var nom;
run;
je n'obtiens pas toutes les infos de contrat.

mais si je change mon var en J'obtiens deux lignes par colonnes.

Je ne comprend pas toute la subtilité du transpose mais comment y ajouter toutes mes variables?
L0007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/12/2010, 15h03   #4
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
bon j'abdique avec la proc transpose. ya surement un moyen mais pour être franc je ne l'utilise quasiment jamais et je ne suis pas fan du tout. si qqn à la soluce uniquementvia transpose je suis preneur.

voici en tout cas une solution

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DATA contrat;
	length idct $3. nom $5. idcl $3. am 3.;
	input idct nom idcl am;
datalines;
101 AAAAA 001 150
102 BBBBB 001 200
103 CCCCC 003 500
;
 
proc transpose DATA=contrat out=pivot2;
	var nom idct am; 
	BY idcl;
run;
 
DATA sortie;
merge pivot2(WHERE=(_name_ IN ("nom"))) 
		pivot2(WHERE=(_name_ IN ("idct"))RENAME=(col1=col3 col2=col4))
		pivot2(WHERE=(_name_ IN ("am"))RENAME=(col1=col5 col2=col6));
	BY idcl;
run;
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/03/2011, 11h33   #5
Invité de passage
 
Homme Aline SINER
Chargée d'étude statistique
Inscription : mars 2011
Messages : 2
Détails du profil
Informations personnelles :
Nom : Homme Aline SINER
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Chargée d'étude statistique
Secteur : Finance

Informations forums :
Inscription : mars 2011
Messages : 2
Points : 3
Points : 3
Bonjour,

J'ai déjà rencontré le même problème et je n'avais pas trouvé comment transposer plusieurs variables dans un même transpose.

J'ai donc fait de l'ensemble de mes variables à transposer une seule variable dans une étape data préalable à la proc transpose.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DATA contrat2 (DROP = IDCT NOM AM COMPTEUR);
    SET contrat2 ;
    BY IDCL;
    IF first.IDCL then COMPTEUR = 0;
    COMPTEUR + 1;
    LIB    =  COMPRESS("idct"||COMPTEUR);
    VALEUR =  idct;
    output;
    LIB    =  COMPRESS("nom"||COMPTEUR);
    VALEUR =  nom;
    output;
    LIB    =  COMPRESS("am"||COMPTEUR);
    VALEUR =  am;
    output;
run;
Ne reste plus ensuite qu'à faire le transpose selon cette nouvelle variable.

Code :
1
2
3
4
5
6
proc transpose DATA= contrat2 
               out = contrat2 (DROP = _NAME_);
    var VALEUR;
    BY idcl;
    id LIB;
run;
On obtient alors :
Obs idcl idct1 nom1 am1 idct2 nom2 am2
1 001 101 AAA 150 102 BBB 200
2 003 103 CCC 500


La dernière étape étant le merge avec la table client1 pour récupérer le nom du client.
Aline S est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/03/2011, 11h45   #6
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
Bonjour Aline,

La solution que j'avais donné au dessus présente une alternative à la proc transpose. As tu essayé avec cette approche?

Si jamais tu n'y arrive pas, merci de nous donner tes données en entrée (ou leur forme au moins), ainsi que la présentation que tu souhaites en sortie..

Manoutz
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/03/2011, 18h13   #7
Invité de passage
 
Homme Aline SINER
Chargée d'étude statistique
Inscription : mars 2011
Messages : 2
Détails du profil
Informations personnelles :
Nom : Homme Aline SINER
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Chargée d'étude statistique
Secteur : Finance

Informations forums :
Inscription : mars 2011
Messages : 2
Points : 3
Points : 3
Bonjour Manoutz,

Excuse-moi, je n'ai pas été claire.

Le code que je proposais permet également de répondre à la question de L0007 avec des étapes préalables à la proc transpose.

Je le réutilise parfois, particulièrement quand j'ai besoin de transposer de nombreuses variables.
Ci-dessous le code dans son intégralité.
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
DATA client1;
	length idcl $3. client $8.;
	input idcl client;
datalines;
001 Bernard
002 Laurent
003 Fabian
;
run;
 
DATA contrat2;
	length idct $3. nom $5. idcl $3. am 3.;
	input idct nom idcl am;
datalines;
101 AAAAA 001 150
102 BBBBB 001 200
103 CCCCC 003 500
;
run;
 
* Création d une seule variable pour les VARIABLES à transposer;
DATA contrat2 (DROP = IDCT NOM AM COMPTEUR);
    SET contrat2 ;
    BY IDCL;
    IF first.IDCL then COMPTEUR = 0;
    COMPTEUR + 1;
    %macro CHANGEVAR (liste=, n=);
        %do i=1 %TO &n;
            %let type= %scan(&liste,&i,%str( ));
            LIB    =  COMPRESS("&type."||COMPTEUR);
            VALEUR =  &type.;
            output;
        %end;
    %mend; 
    %CHANGEVAR (liste = idct nom am , n = 3);
run;
 
proc transpose DATA= contrat2 
               out = contrat2 (DROP = _NAME_);
    var VALEUR;
    BY idcl;
    id LIB;
run;
 
proc sort DATA = contrat2; BY idcl; run;
proc sort DATA = client1 ; BY idcl; run;
 
DATA contrat2;
    merge client1 
          contrat2;
    BY idcl;
run;
La méthode utilisée étant un peu différente de celle que tu proposais, je me suis permise de la rajouter.

Bonne soirée,
Aline S est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/03/2011, 21h17   #8
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
Voici une solution à ton problème.

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
DATA client1;
	length idcl $3. client $8.;
	input idcl client;
datalines;
001 Bernard
002 Laurent
003 Fabian
;
run;
 
DATA contrat2;
	length idct $3. nom $5. idcl $3. am 3.;
	input idct nom idcl am;
datalines;
101 AAAAA 001 150
102 BBBBB 001 200
103 CCCCC 001 300
104 DDDDD 001 400
104 EEEEE 002 700
105 FFFFF 003 500
;
run;
proc sort DATA=contrat2  ;
BY idcl;
run;
proc sort DATA=client1 ;
BY idcl;
run;
DATA clicontra;
merge client1 contrat2;
BY idcl;
run;
 
/* calcul du nombre de colonnes maximale */
proc sql;
CREATE TABLE M AS SELECT  count(*) AS NB FROM clicontra GROUP BY idcl;
SELECT max (NB) INTO:maxx FROM M;
quit;
%put maxx=&maxx;
/*maxx=4 car on a le client 001 sur 4 lignes*/
 
/* une table par variable à dupliquer==> montants en ligne*/
proc transpose DATA=clicontra out=am(DROP=_name_ );
	var am;
	BY idcl;
run;
/* une table par variable à dupliquer==> contrats en ligne*/
proc transpose DATA=clicontra out=idct(DROP=_name_ );
	var idct;
	BY idcl;
run;
/* renommage de COL1-COL&maxx par am&i(i=1 to maxx) et idct&i (i=1 to maxx)*/
%macro M(TABLE=,var=);
	DATA &TABLE.;
	SET &TABLE.; 
	%do i=1 %TO &maxx.;
	RENAME Col&i=&var&i.;
	%end;
	run;
%mend;
%M(TABLE=am,var=am);
%M(TABLE=idct,var=idct);
 
/* on ne garde que idct et le nom du client*/
proc sort DATA=client1 out=Client(keep=idcl client);
	BY idcl;
run;
 
/* fusion des 3 tables */
DATA CLICONTRAT;
	merge Client am client idct;
	BY idcl;
run;
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/03/2011, 08h52   #9
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
Bonjour Aline,

Je ne sais pas si la solution de megamind te convient, il y a peut être plus direct

Permets moi de reposer la question: transposer, oui, mais comment? Quelle forme veux tu en sortie?
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/03/2011, 09h31   #10
Expert Confirmé
 
Avatar de olivier.decourt
 
Homme Olivier Decourt
Formateur en informatique
Inscription : avril 2008
Messages : 1 466
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 466
Points : 2 822
Points : 2 822
Bonjour.
Une petite solution sans TRANSPOSE mais avec des ARRAYS. Pour transposer élégamment plusieurs variables, il faut préparer la table comme le fait Aline si on veut utiliser la proc TRANSPOSE. Sinon on bricole.
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
DATA client1;
	length idcl $3. client $8.;
	input idcl client;
datalines;
001 Bernard
002 Laurent
003 Fabian
;
run;
 
DATA contrat2;
	length idct $3. nom $5. idcl $3. am 3.;
	input idct nom idcl am;
datalines;
101 AAAAA 001 150
102 BBBBB 001 200
103 CCCCC 003 500
;
run;
 
PROC SQL NOPRINT ;
  CREATE TABLE work.tout AS
  	SELECT cli.*,
	       ct.*
	FROM work.client1 AS cli
	  NATURAL INNER JOIN
	     work.contrat2 AS ct
  ;
  SELECT idcl,
         COUNT(*)
	INTO : rien, : nbMax
  FROM work.tout
  GROUP BY idCl
  ORDER BY 2 DESC
  ;
QUIT ;
 
DATA work.tout_en_ligne (DROP=num nom idcl am) ;
  SET work.tout ;
  BY idCl ;
  ARRAY idCont  {&nbMax} $ ;
  ARRAY nomCont {&nbMax} $ ;
  ARRAY amCont  {&nbMax}   ;
  RETAIN ;
  IF FIRST.idCl THEN DO ;
	num = 0 ;
	CALL MISSING(OF idCont(*)) ;
	CALL MISSING(OF nomCont(*)) ;
	CALL MISSING(OF amCont(*)) ;
  END ;
  num + 1 ;
  idCont(num) = idCt ;
  nomCont(num) = nom ;
  amCont(num) = am ;
  IF LAST.idCl THEN OUTPUT ;
RUN ;
Bonne journée.
Olivier
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 03h35.


 
 
 
 
Partenaires

Hébergement Web