h1

La 3ème méthode qui fait la différence pour sélectionner en se basant sur une second data set

février 16, 2009

Suite au précieux conseil d’Arnaud Gaborit (A.I.D.), je vous propose de compléter l’article du 26 janvier dernier intitulé « Deux méthodes pour sélectionner en se basant sur une second data set« . Les personnes travaillant sur de grosses bases de données apprécieront.

Lectures complémentaires :

1. Rappel : les données et le résultat attendu

D’un côté, on a un data set contenant la liste des effets secondaires observés. Il y a une ligne par effet secondaire. Seuls les patients ayant eu un effet secondaire sont enregistrés.

data ae_multi;
   input patref ae_id;
   datalines;
1 1
1 2
2 1
4 1
4 2
5 1
;
run;

De l’autre côté, on a la liste des patients correspondant à la population qui nous intéresse. Une ligne correspond à un patient.

data pat_uniq;
   input patref;
   datalines;
2
3
4
;
run;

Le but est de garder uniquement les effets secondaires des patients présents dans notre population.

patref ae_id

   2     1
   4     1
   4     2

2. Créer un format à partir d’un data set

Dans une premier temps, un format numérique (TYPE=N est la valeur par défaut) appelé PATREF (FMTNAME=’PATREF’) est créé à partir du data set sur les patients. La variable PATREF sert de valeur START. Pour toutes les valeurs de START, on applique le même libellé (LABEL=’retenir’).

Si le data set contient plusieurs variables (ce qui sera généralement le case), l’option KEEP servira à limiter la sélection à la variable servant à définir START.

data pat (keep=start fmtname label);
   set pat_uniq (rename=(patref=start)); *(keep=patref);
   fmtname='PATREF';
   label='retenir';
run;

Si plusieurs valeurs identiques pour la variable START sont présentes dans votre fichier, vous devrez supprimer les doublons. L’étape suivante ne marchera pas sinon.

*proc sort data=pat nodupkey;
*by start;
*run;

Le data set est à présent convertit en format au moyen de l’option CNTLIN. Ce format est sauvegardé par défaut dans le catalogue FORMATS de la bibliothèque WORK.

proc format cntlin=pat;
run;

3. Sélectionner les observations de son choix

Ici, l’option WHERE est privilégiée à l’instruction IF pour des raisons de performance.

Ensuite, grâce à la fonction PUT, les valeurs de PATREF sont converties en RETENIR si elles sont présentes dans le data set PAT_UNIQ. Seules ces valeurs RETENIR sont gardées.

data ae_multi;
   set ae_multi (where=(put(patref,patref.) = 'retenir'));
run;

Voir le résultat :

proc print data=ae_multi;
run;

5 commentaires

  1. Bonjour
    Sauf erreur, il y a également désormais la possibilité d’utiliser une table de « hashage », notamment lorsqu’une des tables est assez petite.

    http://www.sas.com/offices/europe/france/services/support/articles/US200703_a1.html


  2. Très intéressant cette histoire de code HASH !
    Dans le cas d’une sélection, le gain doit être faible par rapport à une sélection via un format, mais dans le cas d’une fusion avec plusieurs variables à récupérer dans la « petite » table, cela pourrait être très performant. Il faut juste se familiariser avec cette nouvelle façon de programmer.. ;o)


  3. Dans le cas d’une sélection, la syntaxe est plus simple …
    ____________________________
    data result;
    length patref 8.;
    if _N_ = 1 then do;
    declare hash h(dataset: « pat_uniq », hashexp: 6);

    h.defineKey(‘patref’);
    * h.defineData(ALL : « YES »);
    h.defineDone();
    end;

    set ae_multi;

    if h.find() then output;

    run;


  4. la syntaxe est plus simple… facile à dire ! ;o)

    Une petite comparaison :
    /* création de 2 tables */
    data big;
    do patref=1 to 10000000;
    v1=ranuni(0);
    v2=ranuni(0);
    v3=ranuni(0);
    v4=ranuni(0);
    v5=ranuni(0);
    v6=ranuni(0);
    output;
    end;
    run;
    proc sort data=big; by v1;run; /* pour que la table ne soit pas triée sur patref */

    data small;
    do i=1 to 50000;
    patref=ceil(ranuni(0)*10000000);
    output;
    end;
    drop i;
    run;
    proc sort nodupkey; by patref; run; /* pour dédoublonner patref */

    /*** sélection par un format ***/
    data pat (keep=start fmtname label);
    set small (rename=(patref=start));
    fmtname=’PATREF’;
    label=’retenir’;
    run;

    proc format cntlin=pat;run;

    data ae_multi;
    set big (where=(put(patref,patref.) ne ‘retenir’));
    run;

    * => temps réel = 1:01.91;

    /*** sélection par code HASH ***/
    data ae_multi;
    length patref 8.;
    if _N_ = 1 then do;
    declare hash h(dataset: « small », hashexp: 6);
    h.defineKey(‘patref’);
    * h.defineData(ALL : “YES”);
    h.defineDone();
    end;
    set big;
    if h.find() then output;
    run;

    * => temps réel = 37.71;

    /*** sélection par un merge ***/
    proc sort data=big; by patref; run;
    data ae_multi; merge big (in=a) small (in=b); by patref; if a and not b; run;

    * => temps réel = 2:16.35;

    Conclusion : Le code HASH est le plus rapide !
    Avec une table BIG plus petite, je n’avais pas d’écart avec la sélection par format. A voir ce qui se passe quand SMALL est plus grosse…

    Remarque : avec ton code j’exclus les obs contenues dans SMALL. J’ai pas réussi à faire l’inverse… :o/


  5. Oui, pardon, en fait h.find()=0 lorsqu’il trouve la valeur (c’est intuitif…).

    Par ailleurs, je trouve la méthode du format vraiment intéressante. Ensuite, c’est à voir selon les cas…



Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :