Précédent   Forum des professionnels en informatique > Logiciels > Solutions d'entreprise > Business Intelligence > SAS > SAS Base
SAS Base Forum d'entraide sur SAS base : étape data, procédures non statistiques, procédures non graphiques, SQL
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 10/08/2011, 17h22   #1
Invité de passage
 
Femme
Étudiant
Inscription : août 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2011
Messages : 4
Points : 0
Points : 0
Par défaut Transformer table ayant plusieurs lignes par individu en table ayant une ligne par individu

Bonjour, je tourne en rond depuis ce matin.

Mon problème est le suivant j'ai pour un individu donné plusieurs lignes selon les activités de loisirs exercées.

Je souhaiterais avoir une seule ligne par sujet et créer autant de variables pour l'activité de loisir en colonne.

exemple :

idsujet actcode actstart actend
10012 1 59 64
10012 2 64 66
10012 3 66 89
10042 1 43 43
10042 2 45 47
10042 3 47 52
10042 4 52 54
10042 5 54 56
10042 6 56 57
10042 7 58 62
10042 8 62 64
10042 9 64 65
10042 10 65 85

Merci pour vos réponses.

J'ai essayé le code suivant pour la variable "actcode" mais ça ne marche pas :

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
DATA loisirs; 
SET loisirs; 
BY idsujet    actcode actstart actend; 
IF first.idsujet then cpt=1; 
else cpt+1; 
run; 
 
 
DATA actlois; 
array actcode (10);
retain actcode1-actcode10; 
SET loisirs; 
BY idnum actcode ; 
IF first.idsujet then do; do i=1 TO 10; 
actcode(i)=""; 
 
end; 
end; 
do j=1 TO 10; 
IF cpt=j then do; 
actcode(j)=actcode; 
end; end; 
IF last.idnum then output; 
run;
soleil777 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2011, 17h44   #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 823
Points : 2 823
Bonjour.
Pour ce genre de traitement qui demande une "vue d'ensemble" de la table, mieux vaut une procédure qu'une étape DATA. Cette dernière ne pourra lire qu'une ligne de données à la fois et du coup, elle manque un peu de recul.
Comme je ne sais pas quelle forme tu veux donner à ton résultat, je t'ai prévu deux solutions, une avec une proc TRANSPOSE et l'autre avec une proc TRANSREG.
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 work.activites ;
  INPUT idsujet $ actcode $ actstart actend ;
DATALINES ;
10012 1 59 64
10012 2 64 66
10012 3 66 89
10042 1 43 43
10042 2 45 47
10042 3 47 52
10042 4 52 54
10042 5 54 56
10042 6 56 57
10042 7 58 62
10042 8 62 64
10042 9 64 65
10042 10 65 85
;
RUN ;
PROC TRANSPOSE DATA=work.activites
                OUT=work.sujet1 (DROP=_name_) ;
  VAR actcode ;
  BY idsujet ;
RUN ;
PROC TRANSREG DATA=work.activites
                DESIGN NOPRINT ;
  MODEL CLASS(actcode / ZERO=NONE SEP="=") ; 
  ID idsujet ;
  OUTPUT OUT=work.sujet2 (DROP=intercept _type_
                               _name_ actcode) ;
RUN ;
Bon courage.
Olivier
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/08/2011, 18h13   #3
Invité de passage
 
Femme
Étudiant
Inscription : août 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2011
Messages : 4
Points : 0
Points : 0
Merci pour cette réponse, mais je ne peux l'appliquer que pour une seule variable, dès que j'en ai 2 ou 3 je suis bloquée.

Ce que je voudrais c pour chaque sujet :

atcode1 actstart1 actend1
atcode2 actstart2 actend2
...
atcode10 actstart10 actend10

Avoir une une ligne par sujet regroupant l'ensemble des activités de loisirs qui seront représentées par colonne c pourquoi j'avais essayé
"actcode1_actcode10" ds le bout de prog sans succès.

J'espère avoir été plus explicite.

Merci pour votre aide
soleil777 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/08/2011, 10h02   #4
Futur Membre du Club
 
Femme
Étudiant
Inscription : juin 2011
Messages : 19
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2011
Messages : 19
Points : 17
Points : 17
En reprenant le code je pense avoir réussi à trouver une solution, pas la plus optimale mais elle a l'air de fonctionner.

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
DATA work.activites ;
  INPUT idsujet $ actcode $ actstart actend ;
DATALINES ;
10012 1 59 64
10012 2 64 66
10012 3 66 89
10042 1 43 43
10042 2 45 47
10042 3 47 52
10042 4 52 54
10042 5 54 56
10042 6 56 57
10042 7 58 62
10042 8 62 64
10042 9 64 65
10042 10 65 85
;
RUN ;
proc sort DATA=activites; BY idsujet actcode actstart actend; run;
DATA sujet;
	SET activites;
	BY idsujet actcode actstart actend; 
	IF first.idsujet then cpt=1; 
	else cpt+1; 
run; 
 
DATA actlois (DROP=j cpt actcode actstart actend); 
	array actcode_tab (10);
	array actstart_tab (10);
	array actend_tab (10);
	retain actcode_tab1-actcode_tab10 actstart_tab1-actstart_tab10 actend_tab1-actend_tab10; 
	SET sujet; 
 
	BY idsujet actcode ; 
	do j=1 TO 10; 
		IF cpt=j then do; 
			actcode_tab(j)=actcode; 
			actstart_tab(j)=actstart; 
			actend_tab(j)=actend; 
		end; 
	end; 
	IF last.idsujet then output;
run;
En espérant avoir aidé.
Mag35 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 11/08/2011, 10h11   #5
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 823
Points : 2 823
Le plus simple c'est de faire autant de proc TRANSPOSE que tu as de variables à pivoter, et ensuite de fusionner (MERGE, SQL, ...) les tables obtenues.
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 work.activites ;
  INPUT idsujet $ actcode $ actstart actend ;
DATALINES ;
10012 1 59 64
10012 2 64 66
10012 3 66 89
10042 1 43 43
10042 2 45 47
10042 3 47 52
10042 4 52 54
10042 5 54 56
10042 6 56 57
10042 7 58 62
10042 8 62 64
10042 9 64 65
10042 10 65 85
;
RUN ;
PROC TRANSPOSE DATA=work.activites
                OUT=work.sujet1 (DROP=_name_) ;
  VAR actcode ;
  BY idsujet ;
RUN ;
PROC TRANSPOSE DATA=work.activites
                OUT=work.sujet1 (DROP=_name_) 
			 PREFIX=actCode ;
  VAR actcode ;
  BY idsujet ;
RUN ;
PROC TRANSPOSE DATA=work.activites
                OUT=work.sujet2 (DROP=_name_) 
			 PREFIX=actstart ;
  VAR actstart ;
  BY idsujet ;
RUN ;
PROC TRANSPOSE DATA=work.activites
                OUT=work.sujet3 (DROP=_name_) 
			 PREFIX=actend ;
  VAR actend ;
  BY idsujet ;
RUN ;
DATA work.sujets ;
  MERGE work.sujet1 work.sujet2 work.sujet3 ;
RUN ;
On peut aussi faire en une seule proc TRANSPOSE à condition de préparer un peu les données en amont
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
DATA work.activites ;
  INPUT idsujet $ actcode actstart actend ;
DATALINES ;
10012 1 59 64
10012 2 64 66
10012 3 66 89
10042 1 43 43
10042 2 45 47
10042 3 47 52
10042 4 52 54
10042 5 54 56
10042 6 56 57
10042 7 58 62
10042 8 62 64
10042 9 64 65
10042 10 65 85
;
RUN ;
DATA work.act ;
  SET work.activites ;
  BY idsujet ;
  ARRAY var actcode actStart actEnd ;
  IF FIRST.idSujet THEN cpt=0 ;
  cpt + 1 ;
  DO OVER var ;
    nomVar = CATS(VNAME(var), cpt) ;
	valeur = var ;
    OUTPUT ;
  END ;
RUN ;
PROC TRANSPOSE DATA=work.act
                OUT=work.sujets1 (DROP=_name_) ;
  VAR valeur ;
  ID nomVar ;
  BY idsujet ;
RUN ;
et aussi avec des ARRAY et une seule étape DATA mais je trouve ça un peu tortueux. J'ajoute un peu de code avant pour savoir quelle taille maxi d'ARRAY j'aurai à créer (10 activité max par sujet dans ton exemple).
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
DATA work.activites ;
  INPUT idsujet $ actcode actstart actend ;
DATALINES ;
10012 1 59 64
10012 2 64 66
10012 3 66 89
10042 1 43 43
10042 2 45 47
10042 3 47 52
10042 4 52 54
10042 5 54 56
10042 6 56 57
10042 7 58 62
10042 8 62 64
10042 9 64 65
10042 10 65 85
;
RUN ;
PROC SQL NOPRINT ;
  SELECT COUNT(*) INTO : nbMaxAct
  FROM work.activites
  GROUP BY idSujet
  ORDER BY 1 DESC ;
QUIT ;
%LET nbMaxAct = &nbMaxAct ; /* supprime les blancs à gauche */
DATA work.sujets2 (DROP=i actCode actStart actEnd) ;
  ARRAY code actcode1-actcode&nbMaxAct ;
  ARRAY start actstart1-actstart&nbMaxAct ;
  ARRAY end actend1-actend&nbMaxAct ;
  i = 0 ;
  DO UNTIL(LAST.idSujet) ;
    SET work.activites ;
    BY idSujet ;
	i+1 ;
    code{i} = actCode ;
    start{i} = actStart ;
    end{i} = actEnd ;
  END ;
  OUTPUT ;
RUN ;
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 11/08/2011, 10h14   #6
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 823
Points : 2 823
Je simplifie juste un peu la proposition de Mag35 (important de penser aux RETAIN !).
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
 
DATA actlois (DROP=j cpt actcode actstart actend); 
	array actcode_tab (10);
	array actstart_tab (10);
	array actend_tab (10);
	retain actcode_tab1-actcode_tab10 actstart_tab1-actstart_tab10 actend_tab1-actend_tab10; 
	SET activites ; 
	BY idsujet ; 
	IF first.idsujet then cpt=1; 
	else cpt+1; 
			actcode_tab(cpt)=actcode; 
			actstart_tab(cpt)=actstart; 
			actend_tab(cpt)=actend; 
	IF last.idsujet then output;
run;
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 11/08/2011, 15h00   #7
Invité de passage
 
Femme
Étudiant
Inscription : août 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2011
Messages : 4
Points : 0
Points : 0
Merci MAG, le pb c que si je rajoute une ligne le programme que t'as proposé affecte par défaut les valeurs des données de l'idnum 10042 à l'idnum10051.

Merci olivier decours,

J'ai remplacé &nbMaxAct par 10, car j'avais un nombre infini de colonnes

et ça a marché.

Mnt j'ai une difficulté supplémentaire car je dois faire la même chose pour une autre table contenant des variables numériques et alphanumériques et je n'y arrive pas.

SAS n'arrive pas à lire les array, merci pour votre aide

Ci dessous un extrait de ma data :

ID PROV JOBTITLE idsujet
1 ON writer 104
2 ON sales 104
3 ON consultant 104
1 ON teacher 115
2 ON Research Scientist 115
3 ON Psost Doctoral Student 115
4 ON MA/PHD student 115
1 ON Manager 238
2 ON sales 104
3 Manager 238
4 ON Technician to manager 238
1 ON teacher 607
1 ON Quality control 548
soleil777 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/08/2011, 16h22   #8
Invité de passage
 
Femme
Étudiant
Inscription : août 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France, Seine et Marne (Île de France)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : août 2011
Messages : 4
Points : 0
Points : 0
Merci infiniment Olivier, j'ai réussis à faire ce que je voulais !

Pour la data où j'avais des variables numériques et alphanumériques, j'ai appliqué le prog sur la partie numérique, puis alphanumérique séparément puis j'ai mergé mes 2 datas.

Mille merci encore

Bonne fin de journée
soleil777 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2011, 11h12   #9
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 703
Points : 1 703
Hello,
pour traiter les variables numériques et alphanumérique séparément dans la même étape data , il faut utiliser :
Code :
1
2
3
 
array {*} _CHARACTER_; *pour toutes les VARIABLES de type alphanumérique;
array {*} _NUMERIC_; *pour toutes les VARIABLES de type munérique;
s_a_m est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h59.


 
 
 
 
Partenaires

Hébergement Web