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 04/05/2011, 11h09   #1
Membre actif
 
Inscription : mai 2004
Messages : 478
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 478
Points : 154
Points : 154
Envoyer un message via MSN à maysa
Par défaut Tableaux et des boucles : do until et array

Bonjour,

je commence l'apprentissage des tableaux et des boucles sous SAS.

J'ai une table, avec différentes dates de visite, une date peut etre vide. J'ai besoin de savoir quand à eu lieu la dernière visite.
Je fais donc un tableau, où je commence par insérer la dernière visite qui était prévue..
Dans ma boucle je lui dis d'initialiser ma variable jusqu'a ce que la variable est vide (comme ça je sais quand a eu lieu ma dernière visite) mais visiblement il ne boucle pas.
Exemple : dans ma table j'ai VS_1 de vide mais pas M9 donc il doit m'initialiser ma date de dernière visite à M9 et non VS_1 . Et bien non..
voici mon code :
Code :
1
2
3
4
5
6
7
8
9
10
 
DATA datevis;
SET datevis;
 ARRAY vis {*} VS_1 M9 M8 M7 J195 M6 J165 M5 M4 M3 J75 M2 J45 M1 J15 dchir M_3 J_7 M_6;
 DO UNTIL (i ^= .);
  dernvis = vis{i};
  i+1;
END;
attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
merci pour votre aide !
maysa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 12h04   #2
Membre éclairé
 
Homme
statisticien
Inscription : mai 2011
Messages : 212
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : statisticien
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : mai 2011
Messages : 212
Points : 319
Points : 319
Bonjour maysa

Personnellement j'ai toujours du mal avec les "DO UNTIL"...

ne sachant pas si tes variables sont classées par date croissante, voici un code dérivé a base de boucle DO i TO max

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
 
 
DATA datevis;
SET datevis;
 ARRAY vis {*} date1 date2 date3 date4;
 DO i=1 TO dim(vis);
  IF vis{i}>dernvis  then dernvis = vis{i};
END;
attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
 
proc print DATA=datevis;run;

Code :
1
2
3
4
5
6
7
 
         Obs         date1         date2         date3         date4    i       dernvis
 
         1              .    09/12/2003    09/12/2004    09/12/2005    5    09/12/2005
         2     09/12/2003             .    09/12/2001             .    5    09/12/2003
         3     09/12/2004    09/12/2008             .    09/12/2003    5    09/12/2008
         4     09/12/2005             .             .             .    5    09/12/2005

sinon avec DO UNTIL en partant de l'envers et avec l'utilisation de dim()

sans dim() je n'y arrive pas...

Code :
1
2
3
4
5
6
7
8
9
10
11
 
DATA datevis;
SET datevis;
 ARRAY vis  {*}  date1 date2 date3 date4;
 i=dim(vis);
DO until (i=0) ;
IF dernvis<vis{i}  then dernvis = vis{i};
  i=i-1;
END;
attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 12h54   #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 823
Points : 2 823
Bonjour.
Ca ne boucle pas parce que i n'est pas initialisé. Donc i=. dès le début de la boucle donc on n'y entre pas.
La solution de Jérôme est très bien.
On peut aussi se passer de l'array : la fonction COALESCE renvoie la 1e valeur non manquante parmi une liste de variables. Il faut donc écrire :
Code :
derVis = COALESCE(visite10, visite9, visite8, etc., visite1) ;
A adapter avec les bons noms de variables, rangés par ordre chronologique décroissant (de la dernière visite à la plus ancienne).
Bon courage.
Olivier
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 13h23   #4
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
Si tu souhaites conserver ton array et sa boucle, il serait plus optimal de le parcourir à l'envers (en partant de la visite la + récente), si j'ai bien compris ton besoin.
Code :
1
2
3
4
5
6
7
8
DATA datevis;
SET datevis;
 ARRAY vis {*} VS_1 M9 M8 M7 J195 M6 J165 M5 M4 M3 J75 M2 J45 M1 J15 dchir M_3 J_7 M_6;
 DO i=DIM(vis) TO 1 BY -1 WHILE(MISSING(vis{i})) ;
 END ;
 dernvis = vis{i};
 attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
A la sortie de la boucle (à cause de la condition, sauf si toutes les dates sont manquantes) i est le numéro du 1er élément non manquant de l'array, parcouru de droite à gauche. Il suffit donc de l'affecter à la nouvelle variable.
L'avantage si seule un petit nombre de dates manque, c'est qu'on fera moins de passages dans la boucle (aucun si la dernière date est renseignée) et qu'on gagnera donc du temps.
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 13h37   #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
Bonjour,

Remarque peut être hors contexte, mais je ne vois pas pourquoi passer par les array. Si j'ai bien compris Mayssa a en entrée un ensemble de variables date ( VS_1 M9 M8 M7 J195 M6 J165 M5 M4 M3 J75 M2 J45 M1 J15 dchir M_3 J_7 M_6) et l'idée est de retenir la date max. Pourquoi ne pas utiliser la finction max dans une étape data ou sql?
Manoutz est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 14h39   #6
Membre actif
 
Inscription : mai 2004
Messages : 478
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 478
Points : 154
Points : 154
Envoyer un message via MSN à maysa
Merci pour vos réponses, je vais tenter d'y répondre individuellement..

oui mes variables sont classées par ordre chronologique... soit ordre décroissant.

Alors j'ai essayé ton code est ça fonctionne ! merci je n'ai même pas pensé à faire de comparaison de date, puisque normalement elles sont dans l'ordre chronologique...

Citation:
Envoyé par jerome_pdv2 Voir le message
Bonjour maysa

Personnellement j'ai toujours du mal avec les "DO UNTIL"...

ne sachant pas si tes variables sont classées par date croissante, voici un code dérivé a base de boucle DO i TO max

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
 
 
DATA datevis;
SET datevis;
 ARRAY vis {*} date1 date2 date3 date4;
 DO i=1 TO dim(vis);
  IF vis{i}>dernvis  then dernvis = vis{i};
END;
attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
 
proc print DATA=datevis;run;

Code :
1
2
3
4
5
6
7
 
         Obs         date1         date2         date3         date4    i       dernvis
 
         1              .    09/12/2003    09/12/2004    09/12/2005    5    09/12/2005
         2     09/12/2003             .    09/12/2001             .    5    09/12/2003
         3     09/12/2004    09/12/2008             .    09/12/2003    5    09/12/2008
         4     09/12/2005             .             .             .    5    09/12/2005

sinon avec DO UNTIL en partant de l'envers et avec l'utilisation de dim()

sans dim() je n'y arrive pas...

Code :
1
2
3
4
5
6
7
8
9
10
11
 
DATA datevis;
SET datevis;
 ARRAY vis  {*}  date1 date2 date3 date4;
 i=dim(vis);
DO until (i=0) ;
IF dernvis<vis{i}  then dernvis = vis{i};
  i=i-1;
END;
attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
maysa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 14h42   #7
Membre actif
 
Inscription : mai 2004
Messages : 478
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 478
Points : 154
Points : 154
Envoyer un message via MSN à maysa
ça foncitonne aussi, sauf que je l'ai fait à l'envers... (parce que mon tableau est créé de façon chronologique..

Code :
DO i=1 TO DIM(vis) WHILE(MISSING(vis{i})) ;
Par contre une chose m'échappe... on initialise dernvis après la boucle ??? . et en dehors de la boucle il connais i ??? y'a que SAS pour faire ça !!

Au final j'ai utilisé la fonction COALESCE, plus rapide , une seule ligne de code...
Merci

Citation:
Envoyé par olivier.decourt Voir le message
Si tu souhaites conserver ton array et sa boucle, il serait plus optimal de le parcourir à l'envers (en partant de la visite la + récente), si j'ai bien compris ton besoin.
Code :
1
2
3
4
5
6
7
8
DATA datevis;
SET datevis;
 ARRAY vis {*} VS_1 M9 M8 M7 J195 M6 J165 M5 M4 M3 J75 M2 J45 M1 J15 dchir M_3 J_7 M_6;
 DO i=DIM(vis) TO 1 BY -1 WHILE(MISSING(vis{i})) ;
 END ;
 dernvis = vis{i};
 attrib dernvis label ="date dernière visite" format= DDMMYY10.;
run;
A la sortie de la boucle (à cause de la condition, sauf si toutes les dates sont manquantes) i est le numéro du 1er élément non manquant de l'array, parcouru de droite à gauche. Il suffit donc de l'affecter à la nouvelle variable.
L'avantage si seule un petit nombre de dates manque, c'est qu'on fera moins de passages dans la boucle (aucun si la dernière date est renseignée) et qu'on gagnera donc du temps.
maysa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 14h43   #8
Membre actif
 
Inscription : mai 2004
Messages : 478
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 478
Points : 154
Points : 154
Envoyer un message via MSN à maysa
Citation:
Envoyé par Manoutz Voir le message
Bonjour,

Remarque peut être hors contexte, mais je ne vois pas pourquoi passer par les array. Si j'ai bien compris Mayssa a en entrée un ensemble de variables date ( VS_1 M9 M8 M7 J195 M6 J165 M5 M4 M3 J75 M2 J45 M1 J15 dchir M_3 J_7 M_6) et l'idée est de retenir la date max. Pourquoi ne pas utiliser la finction max dans une étape data ou sql?
Parce que mes dates sont en colonne et non en ligne...
maysa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 15h00   #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 maysa Voir le message
Parce que mes dates sont en colonne et non en ligne...
Dans une étape data, tu peux avoir le max par ligne comme suit:

Code :
datevisite=max(of date1 date2 date3 date4);
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/05/2011, 15h08   #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
Justement! Dans une étape data, la fonction max() renvoie le maximum d'un ensemble d'arguments (c'est à dire variable, ou encore colonnes). Cette fonction va renvoyer pour chaque la valeur maximum sur un ensemble de colonnes. Donc ça à l'air de coller avec ce que tu veux faire.

En sql, tu peux utiliser cette fonction sur des lignes ou sur des colonnes (ou les deux), il faut donc faire attention à la syntaxe.

Manoutz
Manoutz est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/05/2011, 09h38   #11
Membre actif
 
Inscription : mai 2004
Messages : 478
Détails du profil
Informations forums :
Inscription : mai 2004
Messages : 478
Points : 154
Points : 154
Envoyer un message via MSN à maysa
oui mais en sql, je ne peux faire un max que sur une colonne.. soit
Code :
SELECT max(date) FROM TABLE
je ne pense pas pouvoir lui donner plusieurs colonne...
Mais je ne connaissais pas la fonction max() de l'étape data, alors merci
maysa 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 10h50.


 
 
 
 
Partenaires

Hébergement Web