IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Candidat au Club
    Homme Profil pro
    Statistiques
    Inscrit en
    octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Statistiques

    Informations forums :
    Inscription : octobre 2020
    Messages : 10
    Points : 4
    Points
    4
    Par défaut Découper une table SAS volumineuse en groupes de lignes
    Bonjour,

    Je dois réaliser une proc freq sur une table volumineuse d'environ 10 millions d'observations et 150 variables. Dès que je lance mon programme, SAS plante car la mémoire est insuffisante.
    J'ai essayé de lancer mes proc freq en faisant des groupes de variables mais SAS plante aussi (même quand il n'y a que 2 variables).
    Il est donc préférable de lancer les proc freq en faisant des groupes de lignes et non de colonnes. J'ai donc commencé par faire une data set des 500 000 premières lignes et là ça fonctionne. Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    libname verif "P:\...";
     
    data work.XXX_freq1;
    set verif.XXX (obs=500000);
    run;
     
    ods noresults;
    	ods excel file = "V:\XXX_freq1.xlsx";
    	proc freq data = work.XXX_freq1;
    	tables _all_ / nocol norow nocum nopercent;
        run;
    	ods excel close;
    ods results;
    Seulement, j'aimerais maintenant faire la même chose avec les lignes 500 001 à 1 000 000 et ainsi de suite jusqu'à 10 000 000, mais je bloque.
    Y aurait-il un moyen d'automatiser la procédure ? Les temps de traitement étant assez longs (environ 45 minutes pour les 500 000 premières lignes), j'aimerais lancer mon programme et le faire tourner la nuit pour gagner du temps.

    Je vous remercie d'avance pour votre aide.

    Bien cordialement,

  2. #2
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Vous pouvez éventuellement utiliser une partie de ce code (en l'adaptant à votre besoin)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
     
    %macro tri_splite (lib_source=,
                                tab_source=,
                                lib_interm=,
                                tab_interm=,
                                lib_cible=,
                                tab_cible=,
                                nb_part=,
                                vartri=,
                                compress=);
     
       /* 
       Paramètres : 
       lib_source : nom de la librairie de la table à trier
       tab_source : nom de la table à trier
       lib_interm : nom de la librairie qui contiendra les sous-tables
       tab_interm : préfixe du nom des sous-tables
       lib_cible : nom de la librairie où sera créée la table finale triée
       tab_cible : nom de la table finale triée
       nb_part : nombre de sous-tables
       vartri : variables de tri
       compress : utilisation ou non de la compression
       */
     
       /* Macro-variables locales */
       %local nb_obs nblig i;
     
       /* Détermination du nombre de lignes de la table à trier */
       data _null_;
          ds=open("&lib_source..&tab_source.");
          if ds>0 then do;
             call symput('nb_obs',compress(attrn(ds,"NLOBS")));
          end;
          ds=close(ds);
       run;
     
       /* Calcul du nombre de lignes que contiendra chaque sous-tables */
       %let nblig=%sysfunc(floor(&nb_obs./&nb_part.));
     
       /* Création des sous-tables */
       data %do i=1 %to &nb_part;
               &lib_interm..&tab_interm.&i.
     
               %if &compress ne %str() %then %do;
                  (compress=&compress.)
               %end;
     
            %end;;
          set &lib_source..&tab_source.;
     
          %do i=1 %to %eval(&nb_part-1);
             if _n_ >= %eval(1+(&i.-1)*&nblig.) and _n_ <= %eval(&i.*&nblig.)
             then output &lib_interm..&tab_interm.&i.;
          %end;
          if _n_>=%eval((&i.-1)*&nblig+1) then output &lib_interm..&tab_interm.&nb_part.;
       run;
     
       /* Suppression de la table source */
       proc datasets lib=&lib_source. nolist;
          delete &tab_source.;
       run;
       quit;
     
       /* Tri de chaque sous-tables */
       %do i=1 %to &nb_part;
          proc sort data=&lib_interm..&tab_interm.&i.;
             by &vartri.;
          run;
       %end;
     
       /* Fusion des sous-tables pour obtenir la table triée */
       /* L'option sortedby permet de marquer la table comme étant triée dans l'ordre de tri indiqué */
       data &lib_cible..&tab_cible. (
                                                  %if &compress ne %str() %then %do;
                                                     compress=&compress.
                                                  %end;
                                                  sortedby=&vartri.); 
          set %do i=1 %to &nb_part;
                    &lib_interm..&tab_interm.&i.
                 %end;;
          by &vartri.;
       run;
     
       /* Suppression des sous-tables */
       proc datasets lib=&lib_interm. nolist;
          delete %do i=1 %to &nb_part;
                         &tab_interm.&i.
                      %end;;
       run;
       quit;
     
    %mend tri_splite;
    Cordialement

  3. #3
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11

  4. #4
    Candidat au Club
    Homme Profil pro
    Statistiques
    Inscrit en
    octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Statistiques

    Informations forums :
    Inscription : octobre 2020
    Messages : 10
    Points : 4
    Points
    4
    Par défaut
    Bonjour et merci pour votre retour.

    J'ai essayé d'adapter le code à mes besoins. Pour le moment je cherche juste à créer 20 sous-tables à stocker dans la librairie LIBOUT :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    %let libor = P:\...;
    %let libdes = V:\...
     
    libname libin "&libor.";
    libname libout "&libdes.";
     
     
    %macro freq_volum (lib_source= libin,
                       tab_source= Ent20,
                       lib_interm= libout,
                       tab_interm= _freq,
                       nb_part= 20,
                       compress= Y);
     
       /* 
       Paramètres : 
       lib_source : nom de la librairie de la table à trier
       tab_source : nom de la table à trier
       lib_interm : nom de la librairie qui contiendra les sous-tables
       tab_interm : préfixe du nom des sous-tables
       nb_part : nombre de sous-tables
       compress : utilisation ou non de la compression
       */
     
       /* Macro-variables locales */
       %local nb_obs nblig i;
     
       /* Détermination du nombre de lignes de la table à trier */
       data _null_;
          ds=open("&lib_source..&tab_source.");
          if ds>0 then do;
             call symput('nb_obs',compress(attrn(ds,"NLOBS")));
          end;
          ds=close(ds);
       run;
     
       /* Calcul du nombre de lignes que contiendra chaque sous-tables */
       %let nblig=%sysfunc(floor(&nb_obs./&nb_part.));
     
       /* Création des sous-tables */
       data %do i=1 %to &nb_part;
               &lib_interm..&tab_interm.&i.
     
               %if &compress ne %str() %then %do;
                  (compress=&compress.)
               %end;
     
            %end;;
          set &lib_source..&tab_source.;
     
          %do i=1 %to %eval(&nb_part-1);
             if _n_ >= %eval(1+(&i.-1)*&nblig.) and _n_ <= %eval(&i.*&nblig.)
             then output &lib_interm..&tab_interm.&i.;
          %end;
          if _n_>=%eval((&i.-1)*&nblig+1) then output &lib_interm..&tab_interm.&nb_part.;
       run;
     
    %mend freq_volum;
    Quand je lance le programme rien ne se passe. J'ai sans doute dû me tromper dans les paramètres. J'ai notamment du mal à comprendre ce qu'il faut mettre dans le paramètre "compress". Aucun message d'erreur n'apparait dans le log.

    Cordialement,

  5. #5
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Pour le compress il faut mettre binary
    ou ne rien mettre du tout

    en effet, cette portion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    %if &compress ne %str() %then %do;
                  (compress=&compress.)
    dit que si dans &compress ce n'est pas vide ( %str() ) alors prendre la avleur de &compress
    donc quand vous avez mis "Y" (pour le YES surement) ceci n'est pas reconnu à mon sens

    faite un test avec 2 sous-tables plutôt que les 20 d'un coup, ça vous permettra de valider plus rapidement si cela fonctionne

  6. #6
    Candidat au Club
    Homme Profil pro
    Statistiques
    Inscrit en
    octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Statistiques

    Informations forums :
    Inscription : octobre 2020
    Messages : 10
    Points : 4
    Points
    4
    Par défaut
    J'ai essayé de ne rien mettre dans compress, puis de mettre binary mais rien ne se passe.
    Ce qui est bizarre c'est qu'il n'y a aucun message d'erreur dans la log, seul le code s'affiche en noir. Je dois sans doute me tromper au niveau des paramètres lib_source= libin, tab_source= Ent20 et lib_interm= libout

    J'ai également essayé avec 2 sous-tables mais ça revient au même.

    Je ne pense pas que le fait que j'ai supprimé la fin de la macro pose problème.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Vos tables sont sur quel environnement ?
    je vois en début de votre programme :

    %let libor = P:\...;
    %let libdes = V:\...

    ce sont des tables sur votre environnement "windows" ou des tables sur un environnement "décisionnel" ?

    A la limite, tester cette partie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
       data _null_;
          ds=open("&lib_source..&tab_source.");
          if ds>0 then do;
             call symput('nb_obs',compress(attrn(ds,"NLOBS")));
          end;
          ds=close(ds);
       run;
    en dehors de la macro (juste initialiser les variables nécessaires lib-source et tab_source) et faite un PUT sur la var "nb_obs"
    Déjà de voir si à ce niveau, la table de base est correctement ouverte ou non

  8. #8
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    En fait, la réponse est déjà dans votre premier post :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    ods noresults;
    	ods excel file = "V:\XXX_freq1.xlsx";
    	proc freq data = work.XXX_freq1;
    	tables _all_ / nocol norow nocum nopercent;
        run;
    	ods excel close;
    ods results;
    vous attaquez un excel donc il faut adapter le code de la macro pour intégrer l'ODS

    par contre, j'ai jamais fait une macro avec un ODS, je ne sais pas si cela fonctionne

  9. #9
    Candidat au Club
    Homme Profil pro
    Statistiques
    Inscrit en
    octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Statistiques

    Informations forums :
    Inscription : octobre 2020
    Messages : 10
    Points : 4
    Points
    4
    Par défaut
    Oui je suis bien sur windows. Les chemins fonctionnent bien avec d'autres programmes donc ça devrait le faire ici aussi.
    L'ods fonctionne bien avec une macro. J'y ai déjà eu recours pour d'autres programmes. Le problème ici, est que je voulais déjà créer les sous-tables avant d'exécuter les proc freq exportées en excel (car je sais déjà que cela fonctionne et que l'export est assez long donc je ne veux pas alourdir le programme pour l'instant).
    Désolé je n'utilise SAS que depuis peu de temps et certains concepts sont encore flous...

  10. #10
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    En effet, pour splitter en plusieurs tables votre fichier, il faut en premier pouvoir l'importer. Et vu que c'est un excel, il faut passer par l'ODS

  11. #11
    Candidat au Club
    Homme Profil pro
    Statistiques
    Inscrit en
    octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Statistiques

    Informations forums :
    Inscription : octobre 2020
    Messages : 10
    Points : 4
    Points
    4
    Par défaut
    Le fichier en entrée est bien une table SAS. L'ODS ne me sert qu'à exporter les proc freq au format Excel car c'est plus facile pour moi ensuite.

  12. #12
    Membre à l'essai
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    août 2016
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Finance

    Informations forums :
    Inscription : août 2016
    Messages : 13
    Points : 11
    Points
    11
    Par défaut
    Ok je ne savais pas ce point.

    Avez-vous encore un point bloquant ou avez-vous pu arriver à répondre à votre besoin ?

  13. #13
    Candidat au Club
    Homme Profil pro
    Statistiques
    Inscrit en
    octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Statistiques

    Informations forums :
    Inscription : octobre 2020
    Messages : 10
    Points : 4
    Points
    4
    Par défaut
    J'ai trouvé pourquoi la macro ne s'exécutait pas. J'avais oublié de rappeler le nom de la macro à la fin du code (%freq_volum).
    Tout fonctionne ! J'ai bien 20 tables avec le même nombre d'observations dans mon dossier de destination. Il ne me reste plus qu'à exécuter les proc freq dessus.
    Voici le code qui fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    %let libor = P:\...;
    %let libdes = V:\...;
     
    libname libin "&libor.";
    libname libout "&libdes.";
     
     
    %macro freq_volum (lib_source= libin,
                       tab_source= Ent20,
                       lib_interm= libout,
                       tab_interm= Ent20_freq,
                       nb_part= 20,
                       compress= binary);
     
       /* 
       Paramètres : 
       lib_source : nom de la librairie de la table à trier
       tab_source : nom de la table à trier
       lib_interm : nom de la librairie qui contiendra les sous-tables
       tab_interm : préfixe du nom des sous-tables
       nb_part : nombre de sous-tables
       compress : utilisation ou non de la compression
       */
     
       /* Macro-variables locales */
       %local nb_obs nblig i;
     
       /* Détermination du nombre de lignes de la table à trier */
       data _null_;
          ds=open("&lib_source..&tab_source.");
          if ds>0 then do;
             call symput('nb_obs',compress(attrn(ds,"NLOBS")));
          end;
          ds=close(ds);
       run;
     
       /* Calcul du nombre de lignes que contiendra chaque sous-tables */
       %let nblig=%sysfunc(floor(&nb_obs./&nb_part.));
     
       /* Création des sous-tables */
       data %do i=1 %to &nb_part;
               &lib_interm..&tab_interm.&i.
     
               %if &compress ne %str() %then %do;
                  (compress=&compress.)
               %end;
     
            %end;;
          set &lib_source..&tab_source.;
     
          %do i=1 %to %eval(&nb_part-1);
             if _n_ >= %eval(1+(&i.-1)*&nblig.) and _n_ <= %eval(&i.*&nblig.)
             then output &lib_interm..&tab_interm.&i.;
          %end;
          if _n_>=%eval((&i.-1)*&nblig+1) then output &lib_interm..&tab_interm.&nb_part.;
       run;
     
    %mend freq_volum; 
    %freq_volum;
    Merci beaucoup pour votre aide.

    Cordialement,

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/02/2014, 14h12
  2. Réponses: 5
    Dernier message: 22/05/2008, 16h24
  3. Obtenir la liste des doublons dans une table SAS
    Par marie mouse dans le forum SAS Base
    Réponses: 2
    Dernier message: 05/12/2007, 15h33
  4. [VB6]Problème dajout dans une Table Access à cause des group
    Par bb62 dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 01/02/2006, 10h06
  5. Découper une table access en plusieurs table automatiquement
    Par monsieuryaya2 dans le forum Access
    Réponses: 2
    Dernier message: 29/11/2005, 12h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo