Posts Tagged ‘by’

h1

L’option NOTSORTED de l’instruction BY : A quoi cela sert-il ?

janvier 24, 2010

Dans une instruction BY, l’option NOTSORTED fait parfois son apparition.

Le résultat de cette option diffère de celui avec un tri préalable.

Voici l’illustration de cette option dans un PROC TRANSPOSE.

1. Les données : SASHELP.CLASS

Le dataset SASHELP.CLASS et plus particulièrement ses variables AGE et WEIGHT servent pour l’exemple.

2. Un usage classique de l’instruction BY

De manière générale, pour utiliser une instruction BY,
il faut que les observations soient triées de la même maniÈre dans le fichier d’entrée.

Ici les données sont triées par AGE.

Comme on ne peut pas modifier les fichiers de la bibliothèque SASHELP,
le résultat après le tri est sauvegardé dans la bibliothèque temporaire WORK.

proc sort data=sashelp.class out=class;
by age;
run;

Puis la mesure de poids (WEIGHT) est transposée.

proc transpose data=class out=class;
var weight;
by age;
run;

On se retrouve donc avec une ligne par AGE.

2. L’option NOTSORTED

L’option NOTSORTED se place en fin d’instruction BY.

proc transpose data=sashelp.class out=class;
var weight;
by age notsorted;
run;

Cette fois-ci à chaque changement d’âge dans le fichier d’origine, une nouvelle ligne est ajoutée dans le fichier de sortie.

Par exemple l’âge des observations 2 et 3 du fichier d’origine se suivent : 13.
Dans le fichier final, une seule ligne sera formée à partir de ces deux fichiers. Le premier poids 84 ira dans la variable COL1 et le second 98 dans la variable COL2.

Le même principe s’applique deux autres fois: observations 4 et 5 avec âge=14, observations 6 et 7 avec âge=12.

Lectures complémentaires

h1

Un tableau à une dimension avec PROC FREQ et ODS OUTPUT

juillet 31, 2008

Pour personnaliser une sortie statistique générée par une procédure SAS, il faut parfois convertir ses résultats en tableau (SAS data set). Dans un précédent article, la procédure PROC MEANS a été mise à l’honneur (Diriger la sortie d’un PROC MEANS dans un dataset SAS). Maintenant nous abordons la procédure PROC FREQ dans le cadre d’un tableau à une dimension en combinaison avec l’instruction ODS OUTPUT.

1. Identifier le nom des sorties : un exemple avec une variable

ods trace on/listing;

*Exemple 1 : Proc Freq, une variable;
proc freq data=sashelp.class;
   table age;
run;

ods trace off;

On obtient deux types de tables selon qu’il s’agisse d’un tableau à une dimension ou à plusieurs dimensions.

  • OneWayFreqs: Dans le cas d’un PROC FREQ avec une seule variable, on parle de OneWayFreqs.
  • CrossTabFreqs: Dans le cas d’un tableau croisé, la sortie se nomme CrossTabFreqs.

Output Added:
————-
Name: OneWayFreqs
Label: One-Way Frequencies
Template: Base.Freq.OneWayFreqs
Path: Freq.Table1.OneWayFreqs
————-

1. Identifier le nom des sorties : un exemple avec 2 variables

Dans ce second exemple, deux variables (AGE et SEX)  sont listées. Les statistiques de l’une seront indépendantes des statistiques de l’autre.

ods trace on/listing;

*Exemple 2 : Proc Freq, deux variables;
proc freq data=sashelp.class;
   table age sex;
run;

ods trace off;

Pour distinguer les statistiques de la table SEX de celles de la table AGE, deux outputs sont créés dans la fenêtre OUTPUT. Leur nom (NAME) est identique mais leur chemin d’accès (PATH) varie. On parle de TABLE1 et TABLE2.

Output Added:
————-
Name: OneWayFreqs
Label: One-Way Frequencies
Template: Base.Freq.OneWayFreqs
Path: Freq.Table1.OneWayFreqs
————-

Output Added:
————-
Name: OneWayFreqs
Label: One-Way Frequencies
Template: Base.Freq.OneWayFreqs
Path: Freq.Table2.OneWayFreqs
————-

3. Identifier le nom des sorties : un exemple avec une instruction BY

Avant de se servir d’une instruction BY, les données doivent être triées. La procédure PROC SORT le fait. 

Le data set source est un data set non modifiable. C’est un data set de la bibliothèque SASHELP fournit avec le logiciel SAS.

La version triée est sauvegardée de manière temporaire dans la bibliothèque WORK (bibliothèque par défaut quand son nom n’est pas cité). Ce nouveau dataset s’appelle CLASS.

proc sort data=sashelp.class out=class;
   by sex;
run;

ods trace on/listing;

*Exemple 3 : Proc Freq, une variable et une instruction BY;
proc freq data=class;
   by sex;
   table age;
run;

ods trace off;

Avec une instruction BY, il y a plusieurs outputs pour une seule procédure dans la fenêtre OUTPUT. Les deux sorties ont le même nom (NAME) mais le chemin d’accès (PATH) est différent. On parle de TABLE1 dans les deux cas et de BYGROUP1 et BYGROUP2 pour les distinguer.

Output Added:
————-
Name: OneWayFreqs
Label: One-Way Frequencies
Template: Base.Freq.OneWayFreqs
Path: Freq.ByGroup1.Table1.OneWayFreqs
————-

Output Added:
————-
Name: OneWayFreqs
Label: One-Way Frequencies
Template: Base.Freq.OneWayFreqs
Path: Freq.ByGroup2.Table1.OneWayFreqs
————-

4. ODS OUTPUT et PROC FREQ

L’instruction ODS OUTPUT convertit les sorties dans un data set SAS. Voici donc le résultat de trois PROC PRINT sur les data sets créés avec l’instruction ODS OUTPUT.

4.1 Exemple 1, tableau avec une variable

Dans ce premier exemple, on note, d’une part, la présence de la variable caractère TABLE ; d’autre part, deux variables listent les différentes valeurs prises par la variable AGE : l’une est caractère, l’autre est numérique.

*Exemple 1 : Proc Freq, une variable;
proc freq data=sashelp.class;
   table age;
   ods output onewayfreqs=exemple1;
run;

                                         Cum      Cum
Table     F_Age Age Frequency Percent Frequency Percent

Table Age   11   11     2      10.53       2      10.53
Table Age   12   12     5      26.32       7      36.84
Table Age   13   13     3      15.79      10      52.63
Table Age   14   14     4      21.05      14      73.68
Table Age   15   15     4      21.05      18      94.74
Table Age   16   16     1       5.26      19     100.00

4.2 Exemple 2, tableau avec deux variables

En ajoutant une deuxième variable SEX, des variables supplémentaires sont ajoutées dans la table de sortie. Elles listent les valeurs prises par la variable supplémentaire. Comme précédemment avec la variable AGE, il y a deux variables pour accéder à la fois à l’information sous forme caractère et sous forme numérique a priori. Mais comme ici la variable d’origine est caractère, les deux sont de type caractère.

*Exemple 2 : Proc Freq, deux variables;
proc freq data=sashelp.class;
   table age sex;
   ods output onewayfreqs=exemple2;
run;

                                        Cum      Cum
Table    F_Age Age Frequency Percent Frequency Percent F_Sex Sex

Table Age  11   11     2      10.53        2     10.53
Table Age  12   12     5      26.32        7     36.84
Table Age  13   13     3      15.79       10     52.63
Table Age  14   14     4      21.05       14     73.68
Table Age  15   15     4      21.05       18     94.74
Table Age  16   16     1       5.26       19    100.00
Table Sex        .     9      47.37        9     47.37    F   F
Table Sex        .    10      52.63       19    100.00    M   M

4.3 Exemple 3, tableau avec une instruction BY

Avec l’instruction BY, une seule variable est créée pour distinguer les âges des hommes de ceux des femmes.

*Exemple 3 : Proc Freq, une variable et une instruction BY;
proc freq data=class;
  
by sex;
  
table age;
run;

                                             Cum      Cum
Sex   Table   F_Age Age Frequency Percent Frequency Percent

  Table Age   11   11     1      11.11      1      11.11
 F  Table Age   12   12     2      22.22      3      33.33
 F  Table Age   13   13     2      22.22      5      55.56
 F  Table Age   14   14     2      22.22      7      77.78
 F  Table Age   15   15     2      22.22      9     100.00
 M  Table Age   11   11     1      10.00      1      10.00
 M  Table Age   12   12     3      30.00      4      40.00
 M  Table Age   13   13     1      10.00      5      50.00
 M  Table Age   14   14     2      20.00      7      70.00
 M  Table Age   15   15     2      20.00      9      90.00
 M  Table Age   16   16     1      10.00     10     100.00

NOTE : Dans le cas de l’utilisation de plusieurs PROC FREQ se servant du même OUTPUT (onewayfreqs par exemple), il est conseillé de nettoyer l’ODS OUTPUT avec l’option CLEAR.

ods output clear;

h1

Identifier et supprimer les doublons

juillet 14, 2008

Identifier et supprimer les doublons dans un data set fait partie des compétences de base du programmeur SAS. Trois approches sont envisageables : PROC SQL, PROC SORT et un compteur dans un data step.

Qu’appelle-t-on doublon ? des lignes complètement identiques ou seulement des lignes ayant quelques variables communes ? Il est important de savoir si deux records ayant des observations communes sont considérés comme doublons ou s’il faut que toutes les observations soient identiques. Si seules quelques variables sont considérées, il faut savoir quelle ligne est conservée et lesquelles sont supprimées.

Le data set utilisé pour l’exemple est composé de trois variables CNTRY (country), PAT_ID (patient ID) et VAL (value). Le patient 2 de Chine a trois lignes d’observations dont deux strictement identiques.

cntry    pat_id    val

 CN        1        A
 CN        2        B
 CN        2        C
 CN        2        C
 HK        3        E 

1. PROC SQL

Avec la procédure SQL, il est possible de faire des calculs et de baser sa sélection d’observations sur ce calcul. En d’autres termes, il est possible de compter le nombre de fois qu’une valeur apparaît. Pour identifier les records avec doublons, on prend ceux comptés plus d’une fois.

Première présentation : Voici, tout d’abord, une présentation de PROC SQL décomposable en deux étapes.

proc sql;
   create table two (where=(cnt_pat > 1)) as
      select cntry, pat_id, val, count(*) as cnt_pat
      from one
      group by cntry, pat_id;
quit;

Dans un premier temps, une variable donne le nombre de records par patient dans un pays donné (CNT_PAT) grâce à la syntaxe GROUP BY et la fonction COUNT. A ce stade, on obtient le data set suivant :

cntry pat_id val cnt_pat

  CN     1    A     1
  CN     2    C     3
  CN     2    B     3
  CN     2    C     3
  HK     3    E     1

Dans un second temps, seules les observations ayant des doublons sont gardées, une fois le nouveau data set créé, grâce à l’option WHERE=.

Deuxième présentation : Au lieu de créer la variable CNT_PAT et de faire une sélection ultérieure, la fonction COUNT peut être  ajoutée dans une condition introduite par le mot HAVING et faisant toujours appel à la fonction COUNT.

Pour ne voir qu’une des lignes multiples, il suffit d’ajouter DISTINCT.

proc sql;
   create table two_bis as
   select /*distinct*/ cntry, pat_id, val
   from one
   group by cntry, pat_id
   having count(*) > 1;
quit;

A l’inverse, pour ne sélectionner que les observations n’apparaissant qu’une fois, « >1 » sera remplacé par « =1 ». Seules les observations ayant exactement une occurrence sont sélectionnées.

Le DISTINCT s’applique à l’intégralité des observations. Cela permet de ne garder que des lignes uniques.

Il n’est pas possible de garder la première ligne parmi les doublons définis par des variables précises (CNTRY et PAT_ID dans l’exemple) avec cette méthode.

2. Les options de la procédure PROC SORT (NODUP/NODUPRECS, NODUPKEY)

Il existe deux options dans la procédure PROC SORT pour supprimer les doublons selon qu’ils s’appliquent

  • à toute une ligne d’observation (NODUPRECS dont l’alias est NODUP) ou
  • à une liste de variables précises données dans l’instruction BY (NODUPKEY).

Au choix, le nouveau data set sans doublons remplace l’ancien ou est sauvegardé dans un dataset différent introduit par OUT=.

Les observations ayant été exclues peuvent être sauvegardées dans un nouveau data set dont le nom est défini par DUPOUT=.

proc sort data=one out=three nodupkey dupout=three_bis;
   by cntry pat_id;
run;

proc sort data=one out=four noduprecs /*nodup*/ dupout=four_bis;
   by cntry pat_id;
run;

3. Appliquer une variable compteur

Enfin, après PROC SQL et PROC SORT, une troisième possibilité pour identifier et supprimer les doublons, est d’ajouter une variable compteur.

Dans l’exemple ci-dessous, la variable compteur est nommée CNT. Pour la première observation d’un patient d’un pays donné, le compteur est initialisé à 1. Pour chaque nouveau record du patient, le compteur est incrémenté de 1. Quand la variable CNT est égale à 1, le record est ajouté dans le data set FIVE. Sinon il est ajouté dans le data set FIVE_BIS. A la fin, la variable compteur est supprimée.

Ainsi le data set FIVE contient les records sans doublons. Dans le cas du patient doublonné (patient 2), c’est la première observation qui est conservée.

Dans le data set FIVE_BIS, les records exclus de la première sélection sont conservés.

data five (drop=cnt) five_bis (drop=cnt);
   set one;
   by cntry pat_id val;
   if first.pat_id then cnt=1;
   else cnt+1;
   if cnt = 1 then output five;
   else output five_bis;
run;

Annexe :

data one;
   input cntry $ pat_id $ val $;
   datalines;
CN 1 A
CN 2 B
CN 2 C
CN 2 C
HK 3 E
;
run;

h1

La base de la jointure de deux data sets avec MERGE

mai 29, 2008

Tout d’abord, une jointure c’est quoi ? Une jointure est le rapprochement de plusieurs data sets pour n’en former plus qu’un. Maîtriser les jointures est primordial pour un programmeur. On peut citer deux raisons : fusionner des données est un travail récurrent ; une mauvaise jointure a des conséquences sur toute la suite du travail. La syntaxe de SAS peut paraître triviale. L’important est de connaître ses données et de savoir clairement ce qu’on attend à la fin. Prenez le temps qu’il faut pour acquérir cette compétence, vous ne le regretterez pas.

Les jointures peuvent être définies selon trois critères.

  • Ajouter des variables : on distingue d’un côté les jointures où le but principal est d’empiler des observations les une en dessous des autres (SET, UNION,…) des jointures où le premier but est d’ajouter des variables (MERGE, JOIN,…).
  • Avoir des variables communes aux deux data sets : selon les situations des variables communes doivent être précisées. Parfois, néanmoins, le but est différent et aucune variable commune n’est listée. On s’intéressera au cas le plus fréquent : des variables communes listées.
  • Jointure dans un data set : enfin la syntaxe du data step (SET, MERGE) se distingue de celle de la procédure SQL. Dans le cas présent, on se concentrera sur celle du data step.

Objectif : En résumé, il s’agira de présenter la base de la jointure MERGE, propre au data step, où les variables communes sont listées dans une instruction BY. Voici donc pour commencer trois des quatre situations de base du MERGE avec des variables communes.

Exemples : Dans les exemples qui suivent, il y a deux data sets à chaque fois. Le premier a pour variable A, X, Y, et le second a les variables X, Y et B. Les variables X et Y sont les variables communes. Le résultat de la jointure est un data set nommé FINAL. En fin d’article, vous trouverez le code pour créer rapidement ces différents data sets sources.

1. Différents noms de jointure : si on a deux data sets qui ont une ou plusieurs variables communes, on aura le choix entre plusieurs jointures :

  • ONE-TO-ONE : si dans chaque data set, cette variable (ou la combinaison de ces variables) n’apparaissent qu’une fois, la jointure des deux data sets sera une jointure ONE-TO-ONE.
  • ONE-TO-MANY ou MANY-to-ONE : si un des deux data sets a pour cette variable plusieurs fois la même valeur, la jointure s’appellera ONE-TO-MANY ou MANY-to-ONE.
  • MANY-TO-MANY : maintenant si dans chacun des deux data sets il y a des doublons pour les variables communes, il s’agit d’une jointure MANY-TO-MANY.

2. Des doublons dans aucun des data sets

Dans l’exemple ci-dessous, chacune des combinaisons x=,y= n’apparaît qu’une fois. Une jointure des deux data sets sera ONE-TO-ONE.

Avant deux data sets

   frst_one      second_one
 a    x    y     x    y    b
 1    A    B     B    D    2
 3    C    D     A    B    4
 5    B    D     E    F    6

Après un seul data set

      final
 a    x    y    b
 1    A    B    4
 3    B    D    2
 5    C    D    .
 .    E    F    6

Lister plus de deux data sets ONE-TO-ONE-TO-ONE-TO…: dans ce cas particulier, il est possible de lister plus de deux de data sets ayant tous des BY variables uniques.

2. Des doublons parmi les variables communes dans un et un seul des data sets.

S’il y a des doublons dans un des deux data sets, des lignes supplémentaires seront ajoutées. Et les observations de l’autre data sets seront dupliquées pour chaque doublons.

MANY-TO-ONE : Ici, c’est le premier data set qui a des doublons. La valeur b=4 est répétée pour chacun des x=A, Y=B du premier data set.

Avant deux data sets

  frst_many        second_one
 a    x    y      x    y    b
 1    A    B      B    D    2
 2    A    B      A    B    4
 9    A    B      E    F    6
 3    C    D
 5    B    D

Après un seul data set

      final
 a    x    y    b
 1    A    B    4
 2    A    B    4
 9    A    B    4
 3    B    D    2
 5    C    D    .
 .    E    F    6

ONE-TO-MANY : A l’inverse, ici, c’est le second data set qui a des doublons. C’est donc la valeur a=1 qui est répété pour chaque x=A, Y=B et a=5 pour chacune des combinaisons x=B, y=D du second data set.

Avant deux data sets

  frst_one       second_many
 a    x    y     x    y    b
 1    A    B     B    D    2
 3    C    D     B    D    8
 5    B    D     A    B    3

                 A    B    4
                 E    F    6

Après un seul data set

      final
 a    x    y    b
 1    A    B    3

 1    A    B    4
 5    B    D    2
 5    B    D    8
 3    C    D    .
 .    E    F    6

Après la jointure, il est possible de garder seulement certaines observations. Cela fera l’objet d’un autre article. Jeudi prochain, nous verrons le cas particulier du MANY-TO-MANY.

3. En langage SAS, cela donne quoi?

Quelque soit le type de jointure parmi les trois listées (ONE-TO-ONE, MANY-TO-ONE et ONE-TO-MANY) la syntaxe du MERGE est la même. Je choisi dans cet exemple de nommer le premier data set FRST_… et l’autre SECOND_… Le data set créé s’appelle FINAL. Vous trouverez en bas de l’article le code pour créer ces data sets selon qu’il y a des doublons (FRST_MANY, SECOND_MANY) ou pas (FRST_ONE, SECOND_ONE).

L’instruction BY implique que les données soient préalablement triées de la même manière. Si vous êtes sûr que l’ordre est bon, vous pouvez vous passer d’un tri. Mais c’est rare. Du coup, on a le choix entre un PROC SORT ou un ORDER BY (« GROUP BY ») dans une PROC SQL. 

proc sort data=frst_…;
   by x y;
run;

proc sort data=second_…;
   by x y ;
run;

data final;
   merge frst_… second_…;
   by x y;
run;

Annexe : créer les data sets pour tester les jointures

data frst_one;
   input a x $ y $;
   datalines;
1 A B
3 C D
5 B D
;
run;

data second_one;
  input x $ y $ b;
   datalines;
B D 2
A B 4
E F 6
;
run;

data frst_many;
   input a x $ y $;
   datalines;
1 A B
2 A B
9 A B
3 C D
5 B D
;
run;

data second_many;
   input x $ y $ b;
   datalines;
B D 2
B D 8
A B 3
A B 4
E F 6
;
run;