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 09/12/2010, 13h42   #1
Invité régulier
 
Astrid Genet
Inscription : novembre 2010
Messages : 43
Détails du profil
Informations personnelles :
Nom : Astrid Genet

Informations forums :
Inscription : novembre 2010
Messages : 43
Points : 7
Points : 7
Par défaut Incrémentation d'une variable compteur avec retain

Bonjour,

J'ai crée dans un fichier une variable compteur avec un retain. Mais je veux incrémenter à partir de 1, et non pas 0, et je m'aperçois que bien que j'aie fixé le retain à 1, il incrémente systématiquement à partir de 0. Il doit y avoir dans mon code quelque-chose qui cloche mais je ne vois vraiment pas quoi. Il focntionne parfaitement sinon.

Je vous le met en dessous, si quelqu'un a le temps de regarder je serai ravie. Je ne trouve pas le hic, et au bilan, toute la table est faussée...

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
DATA Verif_JoursManquants;
	SET Meteo1;
	retain NbreJoursConsecutifs 1;
	BY Station element annee mois jour;
	IF Valeur ne "." then DELETE;
	Prev_Jour= lag(Jour);
	PrevMois= lag(mois);
	PrevAnnee= lag(Annee);
	IF Valeur ne "." then DELETE;
	Jour_Prev_Jour=Jour-Prev_Jour;
	Mois_PrevMois=Mois-PrevMois;
	IF Mois= 1 AND Mois-PrevMois= -11 AND Jour-Prev_Jour= -30 then JoursConsecutifs= 1;
	IF (Mois= 2 OR Mois= 4 OR Mois= 6 OR Mois= 8 OR Mois= 9) AND Mois-PrevMois= 1 AND Jour-Prev_Jour= -30 then JoursConsecutifs= 1;
	IF Mois= 3 AND (Annee= 1960 OR Annee= 1964 OR Annee= 1968 OR Annee= 1972 OR Annee= 1976 OR Annee= 1980 OR Annee= 1984 OR Annee= 1988 OR Annee= 1992 
					OR Annee= 1996 OR Annee= 2000 OR Annee= 2004 OR Annee= 2008) AND Mois-PrevMois= 1 AND Jour-Prev_Jour= -28 then JoursConsecutifs= 1;
	else IF Mois= 3 AND Mois-PrevMois= 1 AND Jour-Prev_Jour= -27 then JoursConsecutifs= 1;
    IF (Mois= 5 OR Mois= 7 OR Mois= 10 OR Mois= 12) AND Mois-PrevMois= 1 AND Jour-Prev_Jour= -29 then JoursConsecutifs= 1;
	else IF Mois_PrevMois ne 0 then JoursConsecutifs=0;
	IF Mois_PrevMois = 0 AND Jour_Prev_Jour ne 1 then JoursConsecutifs=0;
	IF Mois_PrevMois = 0 AND Jour_Prev_Jour = 1 then JoursConsecutifs=1;
			IF JoursConsecutifs = 1 then do;
			NbreJoursConsecutifs = NbreJoursConsecutifs + 1;
		end;
		else do;
			NbreJoursConsecutifs = 0;
		end;
run;
Merci!

Astrid
AstridG est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 14h06   #2
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
bonjour Astrid,

ton code est un peu compliqué. un petit peu de ménage ne lui ferait pas de mal. Explique nous ce que tu veux calculer et donne nous un jeu de données.
sasadm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 15h47   #3
Invité régulier
 
Astrid Genet
Inscription : novembre 2010
Messages : 43
Détails du profil
Informations personnelles :
Nom : Astrid Genet

Informations forums :
Inscription : novembre 2010
Messages : 43
Points : 7
Points : 7
Bonjour,

Voici la partie intéressante du code:

Code :
1
2
3
4
5
6
7
8
9
10
DATA Verif_JoursManquants;
	SET Meteo1;
	retain NbreJoursConsecutifs 1;
			IF JoursConsecutifs = 1 then do;
			NbreJoursConsecutifs = NbreJoursConsecutifs + 1;
		end;
		else do;
			NbreJoursConsecutifs = 0;
		end;
run;
Je compte les données manquantes d'un jeu de données qui comporte des mesures quotidiennes repérées par trois variables (Année, Mois, Jour). Je distingue les données manquantes correspondant à des jours consécutifs et les valeurs isolées.
J'ai crée une variable "JoursConsecutifs" qui prend la valeur 0 si la valeur manquante est isolée et 1 si elle est consécutive à une autre. Une illustration:

Annee Mois Jour JourConsecutif
69 2 5 0
69 4 10 0
69 4 11 1
69 4 12 1
69 7 8 0

Puis j'incrémente dans une variable "NbreJoursConsecutifs" pour connaitre la longueur des séries consécutives de données manquantes. Et c'est là qu'est le problème. Je veux initialiser "NbreJoursConsecutifs" à 1 car comme vous le voyez sur l'illustration la première valeur manquante d'une série est notée 0 car elle ne suit pas le jour qui la précède.
Or dans le code affiché plus haut, bien que j'initialise "NbreJoursConsecutifs" à 1 dans mon retain, j'incrémente à partir de 0.

Quelqu'un aurait le fin mot de l'histoire? Est-ce que je n'ai pas le droit d'initialiser ainsi mon retain? Peut-être est il mal placé dans le code?

Merci!

Astrid
AstridG est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 16h33   #4
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
L'initialisation de ta variable retain perdure tant que tu ne modifies pas sa valeur (merci La palice).


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
DATA Verif_JoursManquants;
	SET Meteo1;
	retain NbreJoursConsecutifs 1;
 
               IF JoursConsecutifs = 1 then do;
			NbreJoursConsecutifs = NbreJoursConsecutifs + 1;
		end;
		else do;
			NbreJoursConsecutifs = 0;
		end;
run;
 
/*
Annee Mois Jour JourConsecutif
69 2 5 0
69 4 10 0
69 4 11 1
69 4 12 1
69 7 8 0
*/
Dès la première ligne tu as JoursConsecutifs=0 donc conformément à ton code tu écrases la valeur initiale de NbreJoursConsecutifs par 0.
sasadm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 16h55   #5
Invité régulier
 
Astrid Genet
Inscription : novembre 2010
Messages : 43
Détails du profil
Informations personnelles :
Nom : Astrid Genet

Informations forums :
Inscription : novembre 2010
Messages : 43
Points : 7
Points : 7
Bonjour Sasadm,

Ah oui, c'est à cause du "else do" qui met "NbreJoursConsecutifs" à 0 dans le cas où "JoursConsecutifs" n'est pas égal à 1. Donc ma première valeur nulle de "JoursConsecutifs" initialise effectivement "NbreJoursConsecutifs" à 0. Merci pour votre remarque!

Du coup auriez-vous une idée de l'ajustement dans le code qui permettrait de commencer l'incrémentation à 1 dans le cas d'une série consécutive?

Merci beaucoup,

Astrid
AstridG est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 17h14   #6
Invité régulier
 
Astrid Genet
Inscription : novembre 2010
Messages : 43
Détails du profil
Informations personnelles :
Nom : Astrid Genet

Informations forums :
Inscription : novembre 2010
Messages : 43
Points : 7
Points : 7
J'ai solutionné mon problème, je mets la solution si des fois elle pouvait aider quelqu'un un jour. Cependant c'est un peu de la "bricole", puisque j'ai juste mis NbreJoursConsecutifs = 1 dans l'alternative et je rectifie ensuite au moment de récupérer le nombre de jours manquants dans une variable suivante.

Merci pour votre aide Sasadm!

Astrid
AstridG est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/12/2010, 17h17   #7
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
Tu peux me tutoyer,

Avant de répondre à ta question, je me permets de te donner deux trois notions qui te seront utiles :


1) il existe des dates SAS (0 = 1er janvier 1960, 1 = 2 janvier 1960, aujourd'hui=18605).

2) tu peux calculer facilement la différence (en jours) entre 2 dates grace a la fonction intck.

3) le retain répond à une logique assez destabilisante au début.

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
 
 
/* lecture de date de type JJ/MM/AAAA */
DATA date;
input date ddmmyy10. ;
cards ;
01/01/1960
09/12/2010
10/12/2010
25/12/2010
;
run;
 
/* application d'un format pour plus de confort */
DATA date_format;
SET date ;
format date ddmmyy10.;
run;
 
/*
calcul des intervalles entre les dates
*/
DATA diff;
SET date_format;
retain date_prec 0;
 
format precedente date_prec  ddmmyy10. ; 
 
/* ici,  date prec vaut 0 pour la prmemiere ligne du fait de l'initialisation à 0 du retain,
	puis date_prec égale la date précédente (toujours du fait du retain).
*/
diff=intck('days', date_prec, date);
 
precedente=date_prec; /* pour montrer ce que vaut date_prec à ce niveau de l'étape data */
 
/* date_prec ne vaut réellement la date qui précède que jusqu'à ce qu'il soit écrasée ici : 
*/date_prec=date; 
/* évidemment, cela permet de transmettre la valeur de la date "actuelle" à la ligne suivante... */
 
run;
sasadm 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 18h41.


 
 
 
 
Partenaires

Hébergement Web