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 31/10/2011, 17h38   #1
Membre actif
 
Inscription : juillet 2006
Messages : 295
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 295
Points : 191
Points : 191
Par défaut Optimisation d'étape data pour transposition

Bonjour,

je travaille en SAS/Base et j'ai un petit problème sur une étape data que je n'arrive pas à optimiser. Cela a pour conséquence soit de créer des tables trop grosses qui peuvent bloquer le serveur (problème de place) soit de faire un programme trop lent à tourner (problème de coupure du serveur dans ce cas).

Voici ce que je souhaite faire. Imaginons une table de ce genre :

Code :
1
2
3
4
5
6
7
8
9
10
DATA pb_cbr;
  input individu deb1-deb3 fin1-fin3;
 
  cards;
  1234 0 1 2 3 4 5
  3456 5 . . 9 . .
  4567 3 12 . 4 5 .
  5432 25 65 25 45 78 5
  ;
run;
Mais au lieu d'avoir 3 variables deb et 3 variables fin, j'en ai des centaines. Et au lieu de 4 individus, ce sont des millions.

Je souhaiterais avoir une table avec 2 variables deb et fin et qui, pour chaque individu, compte autant de lignes que de couples début/fin renseignés, soit :

Code :
1
2
3
4
5
6
7
8
9
1234 0 3
1234 2 4
1234 3 5
3456 5 9
4567 3 4
4567 12 5
5432 25 45 
5432 65 78
5432 25 5
Précision : si une variable début est renseignée, la variable fin correspondante l'est également. Si la variable deb_N est vide, les suivantes seront toutes vides.

Initialement, je passais par une proc transpose, mais auparavant, je n'avais pas des centaines de variables mais une cinquantaine seulement. Désormais cela démultiplie les lignes et conduit à une table de 1 milliard de lignes...

J'ai essayé également avec une macro qui ferait autant de set que de couples deb/fin, en sélectionnant uniquement les individus qui ont un couple deb/fin rempli, mais même si le nombre d'individus avec des centaines de couples est réduit, le temps nécessaire à la construction de cette table est... gigantesque...

Code :
1
2
3
4
5
DATA bib.grossetable;
SET %do i=&deb. %TO &fin.;
		bib.table_base (keep=individu deb_&i. fin_&i. WHERE=(deb ne '' AND fin ne '') RENAME=(deb_&i.=deb fin_&i.=fin) )
     %end; ;
run;

Voilà j'espère avoir été clair, si jamais quelqu'un a une idée, je suis preneur !

Merci et bonne journée
Alqualonde est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/10/2011, 19h59   #2
Membre éprouvé
 
Homme Rémi Bousquet
responsable adjoint service stat
Inscription : mars 2009
Messages : 334
Détails du profil
Informations personnelles :
Nom : Homme Rémi Bousquet
Âge : 35
Localisation : France

Informations professionnelles :
Activité : responsable adjoint service stat
Secteur : Finance

Informations forums :
Inscription : mars 2009
Messages : 334
Points : 464
Points : 464
Voilà une piste avec les array, mais je n'ai pas la base permettant de vérifier si les temps de traitement sont réellement optimisés.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
DATA big.grossetable (keep = individu deb fin);
    SET work.pb_cbr ;
    array debi(*) deb1-deb3 ;
    array fini(*) fin1-fin3 ;
    do loop = 1 TO 3 ;
        IF    NOT missing(debi(loop))  
           /*and not missing(debi(fin))*/ /*?*/
            then do ;
            deb = debi{loop} ;
            fin = fini{loop} ;
            output ;
        end ;
    end ; 
run ;
Piste d'amélioration (?) :
- es tu certain que les length de tes var debi et fini sont optimisées ?
- l'option compress te permettrait de réduire la taille de la base sur le serveur (mais à voir si ça accélère ou ralonge les temps de traitement)
RemiBousquet est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 01/11/2011, 10h53   #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 828
Points : 2 828
Bonjour.
Je +1 par rapport à la solution de Rémi. Je la modifie juste très légèrement (j'intègre le IF à la boucle histoire de profiter de ce que "Si la variable deb_N est vide, les suivantes seront toutes vides.") pour gagner encore un peu de temps.
Code :
1
2
3
4
5
6
7
8
9
10
11
DATA big.grossetable (keep = individu deb fin);
    SET work.pb_cbr ;
    array debi(*) deb1-deb3 ;
    array fini(*) fin1-fin3 ;
    LENGTH deb fin 3 ; /* à ajuster en fonction des valeurs */
    do loop = 1 TO DIM(debi) WHILE (NOT missing(debi(loop))) ;
            deb = debi{loop} ;
            fin = fini{loop} ;
            output ;
    end ; 
run ;
Cela dit, je suppose que produire cette table n'est pas ton but ultime. Si tu nous décris un peu ce que tu veux faire ensuite, peut-être pourrons-nous te proposer des méthodes qui évitent de créer de trop grosses tables pour arriver à tes fins.

Bon courage.
Olivier
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/11/2011, 11h02   #4
Membre actif
 
Inscription : juillet 2006
Messages : 295
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 295
Points : 191
Points : 191
Bonjour !

Merci beaucoup à vous deux pour ces réponses très précises et ô combien précieuses !
J'avais bien tenté de faire un output en cours d'étape data mais je n'avais pas réussi à formaliser le programme suffisamment pour que ça marche.

En testant vos programmes, cela marche non seulement parfaitement, mais en un temps qui dépasse mes espérances (environ 3 minutes !) Bref un grand merci
Alqualonde 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 10h17.


 
 
 
 
Partenaires

Hébergement Web