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 14/10/2011, 10h44   #1
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Par défaut Comment dé-cumuler une variable

Bonjour,

Encore un nouveau souci dans SAS .... et en essayant avec des last, retain, je ne m'en sors pas.

Voici le problème : je cherche à décumuler une variable, l'exemple suivant sera plus explicite qu'un long texte

Date Client Montant cum Montant dé-cumulé voulu
31/01/2009 AAA 0 0 (1ère situation reste inchangé)
28/02/2009 AAA 100 100 (100-0)
31/03/2009 AAA 200 100 (200-100)
30/04/2009 AAA 400 200 (400-200)
31/05/2009 AAA 700 300 (700-400)
30/06/2009 BBB 10 10 (1ère situation reste inchangé)
31/07/2009 BBB 100 90 (100-10)
31/08/2009 BBB 500 400 (500-100)
30/09/2009 BBB 1000 500 (1000-500)


Est-ce quelqu'un pourrait m'expliquer comment faire pour obtenir la colonne "montant dé-cumulé voulu" ???

Merci beaucoup pour votre aide !
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/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

je te propose de classer tes observations par client et montant cumulé si ce n'est pas déjà fait.
Code :
1
2
 
proc sort DATA=TABLE; BY client montant_cum;run;
Ensuite tu utilise LAG(X)

Code :
1
2
3
4
5
6
 
DATA table2;SET TABLE;
BY client;
IF first.client then montant_decum=montant_cum;
else montant_decum=montant_cum-lag(montant_cum);
run;
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 12h50   #3
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Ca fonctionne !!!!

merci mille fois !
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 15h10   #4
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
En fait, j'ai trouvé un problème dans le résultat du programme
Voila ce qu'il me donne :

Date Client Montant cum Montant dé-cumulé voulu
31/01/2009 AAA 0 0 (1ère situation reste inchangé)
28/02/2009 AAA 100 100
31/03/2009 AAA 100 0
30/04/2009 AAA 200 100
31/05/2009 AAA 200 0
30/06/2009 BBB 0 0
31/07/2009 BBB 0 -200 ???????
31/08/2009 BBB 100 100
30/09/2009 BBB 100 0

Je ne comprends pas pourquoi il me fait ca .. il se base sur la situation d'un autre client alors qu'il ne devrait pas ...
Une idée pour résoudre ce problème ???

Deuxième point : j'aimerais lui dire que si la différence d'un mois à l'autre est nul, alors il me garde la valeur dé-cumulée non nulle précédente. Pour obtenir au final :

Date Client Mt_cum Mt_décumulé_voulu Mt_décum_final
31/01/2009 AAA 0 0 -> 0
28/02/2009 AAA 100 100 -> 100
31/03/2009 AAA 100 0 -> 100
30/04/2009 AAA 400 300 -> 300
31/05/2009 AAA 400 0 -> 300
30/06/2009 BBB 0 0 -> 0
31/07/2009 BBB 0 0 -> 0
31/08/2009 BBB 100 100 -> 100
30/09/2009 BBB 100 0 -> 100

Merci à toutes les bonnes âmes qui prendront le temps de m'aider !
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 15h29   #5
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
Ok pour ta première question, je vois le truc, je ne sais pas comment nous en débarrasser "proprement", mais on peut contourner le problème

Code :
1
2
3
4
5
6
7
 
DATA table2;SET TABLE;
BY client;
soustract=lag(montant_cum);
IF first.client then soustract=0; 
montant_decum=montant_cum-soustract;
run;
Edit :

Pour ta deuxième question, sur le même principe, tu as essayé par exemple de mettre ceci à la fin ?

dern_val=lag(montant_decum);
if montant_decum=0 then montant_decum=dern_val;

Si les dates sont importantes pour toi n'oublie pas de mettre la date dans les variables de tri (en dernier : soit dans le sort by client montant_cumul date; sans toucher au by de l'étape data ).
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 15h37   #6
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
C'est nikel !! les valeurs négatives ont disparu !
Et il redémarre bien là où il faut par client !
merci bcp bcp !!!

Pour ma deuxième question, est ce que tu sais comment je peux faire pour lui dire de garder le mt décumulé non nul, date par date, jusqu'à ce qu'il trouve un autre mt décumulé non nul et ainsi de suite ... ?????
J'ai mis un exemple dans mon mail précédent si ce n'est pas très clair par écrit
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 16h07   #7
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
En fait, j'avais aussi essayer de passer par une nouvelle variable LAG(mt_decum) en l'intégrant dans le programme, mais ca ne fonctionnait pas.
J'ai essayé avec ta proposition ... mais même erreur ...

En fait, j'ai trouvé : cela ne fonctionnait pas parce qu'il faut créer cette nouvelle variable dans un autre data step ... certainement parce qu'elle se base sur une variable créée dans le 1er programme ...

En tout cas, en passant par un nouveau data step, ca fonctionne !!
Ouf !

En tout cas, vraiment vraiment merci pour ton aide !!
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 16h49   #8
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
je suis désespérée ...

ca a marché une fois en passant par des tables tests
mais maintenant que je veux intégrer tout ca pour travailler sur mes vrais données, ca ne fonctionne plus a cause de la variable dern_val qui ne garde pas à toutes les situations les valeur non nulles décumulées ...

voila ce que j'ai :
date mt_cum mt_decum dern_val
31/01/2009 0 0 0
28/02/2009 500 500 0
31/03/2009 500 0 devient 500 500
30/04/2009 500 0 devrait être 500 0 (on veut avoir 500 ...)

au secours je deviens folle !!!!!!
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 17h47   #9
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Voila mon programme :
A noter que la table test00 est une table trier (proc sort) par client, mt_cum et date.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
DATA WORK.TEST01 ;SET WORK.TEST00;
BY client ;
soustract = lag(mt_cum);
IF first.client THEN soustract = 0 ; 
   mt_decum = mt_cum - soustract;
RUN ;
 
DATA WORK.TEST02 ; SET WORK.TEST01 ;
BY client ;
dern_val=lag(mt_decum);
IF mt_decum = 0 THEN mt_decum = dern_val;
RUN ;
voila le résultat pour un client :

table initiale :
date mt_cum soustract mt_decum
31/01/2009 0 0 0
28/02/2009 500 0 500
31/03/2009 500 500 0
30/04/2009 500 500 0


table de résultat:
date mt_cum soustract mt_decum dern_val
31/01/2009 0 0 0 0
28/02/2009 500 0 500 0
31/03/2009 500 500 500 500
30/04/2009 500 500 0 0

comme constaté, le pb se pose sur la dernière ligne dans ce cas précis :
nous devrions avoir dern_val = 500 et donc mt_decum = 500

Est-ce que qq un voit où est le problème ???

Un grand merci par avance.
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 17h59   #10
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
Pourquoi vous n'aviez pas utilisé le DIF ? si la valeur d'après est inférieure à la valeur d'avant alors le decum est négatif.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
DATA test;
input Date :ddmmyy10. Client $ Montant;
datalines;
31/01/2009 AAA 0 
28/02/2009 AAA 100 
31/03/2009 AAA 200
30/04/2009 AAA 400
31/05/2009 AAA 700
30/06/2009 BBB 10 
31/07/2009 BBB 100
31/08/2009 BBB 500
30/09/2009 BBB 100
;
run;
 
DATA test;
SET test;
BY client;
decum = dif(montant);
IF first.client then decum=montant;
run;
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 18h05   #11
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
pour la deuxième question, tu veux cela ?

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 test;
input Date :ddmmyy10. Client $ Montant;
datalines;
31/01/2009 AAA 0 
28/02/2009 AAA 100 
31/03/2009 AAA 100
30/04/2009 AAA 400
31/05/2009 AAA 700
30/06/2009 BBB 10 
31/07/2009 BBB 100
31/08/2009 BBB 500
30/09/2009 BBB 100
;
run;
 
DATA test;
SET test;
BY client;
decum = dif(montant);
lmontant=lag(montant);
IF decum=0 then decum=lmontant;
IF first.client then decum=montant;
DROP lmontant;
run;
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 18h07   #12
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
J'obtiens aussi :

date client mt_cum mt_decum
31/01/2009 AAA 0 0
28/02/2009 AAA 500 500
31/03/2009 AAA 500 0
30/04/2009 AAA 500 0
31/05/2009 AAA 600 100
30/06/2009 AAA 600 0
31/07/2009 AAA 600 0

Mon souci est que je veux garder le mt_decum à la place des 0
donc par exemple au 31/03/2009, SAS doit me mettre 500 de mt_decum, idem pour le 30/04/2009
pour le 30/06/2009, il doit me garder 100 comme mt_decum
et ainsi de suite ...
ma table contient ainsi des milliers de clients pour lesquels il faut généraliser tout ceci ....
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 18h15   #13
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
cela ne fonctionne pas en utilisant ta solution : voila ce que j'obtiens :

date client mt_cum mt_decum
31/01/2009 AAA 0 0
28/02/2009 AAA 500 500
31/03/2009 AAA 500 500
30/04/2009 AAA 500 500
31/05/2009 AAA 600 100
30/06/2009 AAA 600 600 -> faux, devrait etre 100
31/07/2009 AAA 600 600 -> faux, devrait etre 100
31/08/2009 AAA 800 200
30/09/2009 AAA 800 800 -> faux, devrait etre 200
31/10/2009 AAA 800 800 -> faux, devrait etre 200
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/10/2011, 18h57   #14
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
re

sur la base du code posté par datametrics

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 test;
input Date :ddmmyy10. Client $ Montant;
datalines;
31/01/2009 AAA 0 
28/02/2009 AAA 100 
31/03/2009 AAA 100
30/04/2009 AAA 400
31/05/2009 AAA 700
30/06/2009 BBB 10 
31/07/2009 BBB 100
31/08/2009 BBB 500
30/09/2009 BBB 500
31/10/2009 BBB 500
30/11/2009 BBB 700
;
run;
 
DATA test;
SET test;
BY client;
retain lmontant;
decum = dif(montant);
IF lag(decum)^=0 then lmontant=lag(decum); 
IF decum=0 then decum=lmontant;
IF first.client then decum=montant;
DROP lmontant;
run;
 
proc print DATA=test;run;
ce qui donne

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
                            Obs     Date    Client    Montant    decum
 
                              1    17928     AAA          0         0
                              2    17956     AAA        100       100
                              3    17987     AAA        100       100
                              4    18017     AAA        400       300
                              5    18048     AAA        700       300
                              6    18078     BBB         10        10
                              7    18109     BBB        100        90
                              8    18140     BBB        500       400
                              9    18170     BBB        500       400
                             10    18201     BBB        500       400
                             11    18231     BBB        700       200
ça va ?
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/10/2011, 14h26   #15
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Bonjour,

Je ne pourrais essayer ta solution que demain matin au boulot.
Je reviendrais donc demain pour dire si ça a fonctionné.

Merci d'avance !
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 07h39   #16
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Par défaut Manqeu balises [code] [/code]

Bonjour,

Faisant suite à ton programme

Code :
1
2
3
4
5
6
7
8
9
DATA test;
SET test;
BY client;
retain lmontant;
decum = dif(montant);
IF lag(decum)^=0 then lmontant=lag(decum); 
IF decum=0 then decum=lmontant;
IF first.client then decum=montant;
DROP lmontant
Je ne sais pas à quoi correspond le ^ dans ton programme .. Peux-tu m'expliquer ce que c'est ??

Merci par avance.
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 08h17   #17
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Si j'enlève cette sorte d'accent circonflexe, voici ce que j'obtiens :

date client mt_cum mt_decum
01/2009 A 0 0
02/2009 A 500 500
03/2009 A 500 0
04/2009 A 500 500
05/2009 A 1500 1000
06/2009 A 1500 0
07/2009 A 1500 1000
01/2009 B 0 0
02/2009 B 100 100
03/2009 B 100 -1500
04/2009 B 100 100
05/2009 B 500 400
06/2009 B 500 0
07/2009 B 500 400


et avec l'accent circonflexe, je m'éloigne encore plus de la solution ...
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 10h10   #18
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
le chapeau chinois signifie "différent" donc ^= signifie n'est pas égal à
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 10h13   #19
Invité régulier
 
Femme
Inscription : octobre 2011
Messages : 30
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : octobre 2011
Messages : 30
Points : 7
Points : 7
Ok, merci pour l'information !!!
Chicou17 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2011, 10h13   #20
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 828
Points : 2 828
Bonjour à tous.
^= signifie "différent de". On peut aussi écrire NE (Not Equals), ce qui me semble une écriture plus robuste.
Par ailleurs, je ne suis pas certain d'avoir tout compris à ton cahier des charges, Chicou17, mais je trouve que la solution actuelle, avec des LAG sous condition, des LAG dans la condition à évaluer, tout ça fait un peu rafistolage. Si tu as besoin de savoir qu'un montant ne varie pas, utilise des blocs BY sur le montant par client.
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
DATA test;
input Date :ddmmyy10. Client $ Montant;
datalines;
31/01/2009 AAA 0 
28/02/2009 AAA 100 
31/03/2009 AAA 100
30/04/2009 AAA 400
31/05/2009 AAA 700
30/06/2009 BBB 10 
31/07/2009 BBB 100
31/08/2009 BBB 500
30/09/2009 BBB 500
31/10/2009 BBB 500
30/11/2009 BBB 700
;
run;
 
DATA work.test ;
  SET work.test ;
  BY client montant ;
  RETAIN mt_prec ;
  decum = DIF(montant) ;
  IF FIRST.client THEN decum=montant ;
  IF decum = 0 THEN decum = mt_prec ;
  IF NOT LAST.montant THEN mt_prec = decum ;
RUN ;
Je ne sais pas si ça fonctionne mieux, à toi de nous éclairer. S'il y a un cas non traité, merci de le rajouter au jeu d'essai en indiquant quelle réponse est attendue et sa logique.
Bon courage.
Olivier
olivier.decourt 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 07h15.


 
 
 
 
Partenaires

Hébergement Web