Posts Tagged ‘condition’

h1

Les anniversaires, cela se fête avec SAS

avril 2, 2009

Aujourd’hui étant mon anniversaire, je fais la paresseuse et vous communique un petit fichier SAS, reçu ce jour (merci Alex), à faire tourner sous Windows, écouteurs en place, pour la prochaine fois qu’un collègue ou pote qui connaît SAS soufflera ses bougies. Amusez-vous bien !

%let pc=1;

%macro sasreference_fr(note,octave,length);

select(&note.);
when (‘A’) call sound (55*(2**&octave.),&length.*160*&pc.);
when (‘A#’) call sound (58*(2**&octave.),&length.*160*&pc.);
when (‘Bb’) call sound (58*(2**&octave.),&length.*160*&pc.);
when (‘B’) call sound (62*(2**&octave.),&length.*160*&pc.);
when (‘C’) call sound (65*(2**&octave.),&length.*160*&pc.);
when (‘C#’) call sound (69*(2**&octave.),&length.*160*&pc.);
when (‘Db’) call sound (69*(2**&octave.),&length.*160*&pc.);
when (‘D’) call sound (73.5*(2**&octave.),&length.*160*&pc.);
when (‘D#’) call sound (73.5*(2**&octave.),&length.*160*&pc.);
when (‘Eb’) call sound (78*(2**&octave.),&length.*160*&pc.);
when (‘E’) call sound (82*(2**&octave.),&length.*160*&pc.);
when (‘F’) call sound (87*(2**&octave.),&length.*160*&pc.);
when (‘F#’) call sound (92.5*(2**&octave.),&length.*160*&pc.);
when (‘Gb’) call sound (92.5*(2**&octave.),&length.*160*&pc.);
when (‘G’) call sound (98*(2**&octave.),&length.*160*&pc.);
when (‘G#’) call sound (104*(2**&octave.),&length.*160*&pc.);
when (‘Ab’) call sound (104*(2**&octave.),&length.*160*&pc.);
when (‘R’) call sleep((&length./3)*&pc.,1);
otherwise;
end;
%mend sasreference_fr;

data _null_;
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘D’,3,2);
%sasreference_fr(‘C’,3,2);
%sasreference_fr(‘F’,3,2);
%sasreference_fr(‘E’,3,4);

%sasreference_fr(‘R’,3,2);

%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘D’,3,2);
%sasreference_fr(‘C’,3,2);
%sasreference_fr(‘G’,3,2);
%sasreference_fr(‘F’,3,4);

%sasreference_fr(‘R’,3,2);

%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,3,1);
%sasreference_fr(‘C’,4,2);
%sasreference_fr(‘A’,4,2);
%sasreference_fr(‘F’,3,1);
%sasreference_fr(‘F’,3,1);
%sasreference_fr(‘E’,3,2);
%sasreference_fr(‘D’,3,4);

%sasreference_fr(‘R’,3,2);

%sasreference_fr(‘Bb’,4,1);
%sasreference_fr(‘Bb’,4,1);
%sasreference_fr(‘A’,4,2);
%sasreference_fr(‘F’,3,2);
%sasreference_fr(‘G’,3,2);
%sasreference_fr(‘F’,3,4);
run;

Pour les curieux, je vous invite à consulter les programmes des chansons suivantes suggérées sur le forum de developpez.com :

Les plus téméraires s’intéresserons à la publication « Making Music in SAS« . Vos créations pourront être publiées sur le blog.

A lire aussi www.sasreference.fr :

h1

5 points à retenir sur l’opérateur logique LIKE

décembre 14, 2008

Comment dire à SAS de sélectionner toutes les observations pour lesquelles une variable donnée contient le mot CASTS ? L’opérateur logique LIKE, utilisable uniquement une condition exprimée par WHERE est fait pour ce travail. Voici donc 5 points à retenir sur LIKE que vous pourrez vous même vérifier à l’aide du data set founi en bas d’article dans la rubrique « Annexe » et des exemples de la section 2.

1. Les 5 points à retenir sur LIKE

1. Trouver un texte ayant une structure donnée : Le but de LIKE est de trouver, pour une variable donnée, toutes les observations ayant une structure particulière.

2. Traiter des chaînes de caractères : LIKE s’applique à une chaîne de caractères et non à des valeurs numériques.

3. Autoriser un caractère libre : Le tiret bas (underscore : _) désigne qu’il faut absolutement un caractère à l’endroit où il est utilisé : ni plus ni moins.

4. Autoriser une chaîne de caractère libre : Le pourcentage (percent : %) accepte toute chaîne de caractère, quelque soit sa longueur, à l’endroit où le symbole apparaît. L’absence de caractère est aussi valide.

5. Appliquer LIKE dans un WHERE : LIKE s’utilise uniquement avec WHERE dans une étape data ou dans la procédure SQL. Il ne fonctionnera pas avec IF.

2. Quelques exemples

Un exemple avec les pourcentages : Dans ce premier exemple, on sélectionne toutes les lignes d’observations où la variable TEST_LAB contient le mot CASTS en majuscule. Il est possible de prendre une observation contenant du texte ou des blancs avant le mot CASTS et/ou après le mot CASTS.

data casts;
   set lab (where=(test_lab like '%CASTS%'));
run;

Pour prendre toutes les observations indépendamment de la case ajouter la fonction UPCASE autour du nom de la variable UPCASE(TEST_LAB) like…

Un exemple avec le tiret bas : imaginons que vous vouliez repérer toutes les tests en rapport avec « Leukocyte esterase » mais vous envisagerez une mauvaise saisie au niveau du k, c et y. Vous demandez alors toutes les observations ressemblant au mot « Leukocyte esterase » en acceptant n’importe quelle autre valeur pour k, c et y.

data check_leuk;
   set lab (where=(test_lab like 'LEU_O__TE ESTERAS'));
run;

Un exemple combinant pourcentage et tiret bas : dans ce troisième et dernier exemple, on cherche à trouver toutes les observations contenant le mot CAST tout en assumant que la lettre A peut être erronnée dans les données du data set LAB. N’importe quel caractère à l’emplacement du A est autorisé.

data check_casts;
   set lab (where=(test_lab like '%C_ST%'));
run;

La même chose avec PROC SQL

proc sql;
   create table check_casts as
       select *
       from lab
       where test_lab like '%C_ST%';
quit;

Annexe : CASTS réfère à des tests de laboratoires sur les urines (urinal test).

data lab;
   length test_label $100;
   input test_label $;
   datalines;
FATTY CASTS
GRANULAR CASTS
HYALINE CASTS
RED BLOOD CELL COSTS
LEUKOCYTE ESTERASE
RENAL TUBULAR EPITHELIAL CASTS
WAXY CASTS
WHISTE BLOOD CELL CASTS
KETONE
;
run;
h1

Penser conditionnel (3/3) : CASE WHEN

juillet 3, 2008

Après avoir présenté les deux alternatives sous SAS dans un data step pour définir des conditions (La base du IF et SELECT), partons voir la syntaxe de PROC SQL pour définir une nouvelle variable.

1. Différences et ressemblances avec les IF et SELECT

Différences : A la différence des deux syntaxes du data step,…

  • … une seule action est possible pour une condition donnée : à savoir définir une et une seule nouvelle variable ou macro variable. Les conditions ne peuvent dont pas servir pour créer de nouveaux data sets ou imbriquer des conditions dans d’autres conditions.
  • … le nom de la nouvelle variable n’est donné qu’une seule fois.

Ressemblances :

  • Comme dans SELECT WHEN et ELSE IF,  seuls les records non déjà valides pour les cas listés précédemment sont relus.
  • Comme IF THEN, une dernière condition ELSE liste tous les cas non sélectionnés auparavant.

Un des avantages de la procédure SQL est de pouvoir définir une nouvelle variable à partir d’une ancienne variable portant le même nom. Alors que dans un data step, cela se passe en plusieurs étapes : 

  • Tout d’abord, la variable est renommée pour pouvoir se servir de son nom d’origine pour la nouvelle variable.
  • Ensuite la variable d’origine portant le nom créé uniquement pour l’occasion est supprimée.

Un autre avantage est l’usage des fonctions et du mot-clé DISTINCT.

2. La syntaxe CASE WHEN en exemple

2.1 Définir une variable à partir de plusieurs variables

Dans cet exemple, la variable POP prend au maximum 4 valeurs :

  • 1 si la variable AGE est supérieure à 13 et la variable SEX est égale à F ;
  • 2 si l’AGE est entre 0 et 13 et qu’il s’agit d’une femme ;
  • 3 si il s’agit d’un homme et que l’âge est une valeur positive ;
  • valeur manquante enfin pour les autres cas.

proc sql;
   /*create table class as*/
   select *, case
               when age > 13 and sex=‘F’ then 1
               when age >= 0 and sex=‘F’ then 2
               when age < 0 or sex not in (‘F’,‘M’) then .
               else 3
           end as pop
   from sashelp.class;
quit;

2.2 Utiliser les fonctions

Dans l’exemple ci-dessous, le critère est appliqué par groupe de valeurs définies dans la variable SEX. En regardant les données, deux groupes de valeurs apparaissent : ‘F’ pour les femmes et ‘M’ pour les hommes. La variable MAX_AGE1 est égale à ’13’ si, pour un groupe donné, la valeur maximale observée parmi les valeurs non manquantes de la variable AGE est 13. Sinon, MAX_AGE1 prend la valeur ‘N/A’.

proc sql;
   select sex, case
                 when max(age) = 13 then ’13’
                 else ‘N/A’
               end as max_age1
   from sashelp.class
   group by sex;
quit;

A présent, vu qu’il n’y a qu’un critère définissant la condition et qu’une seule valeur n’est attendue, ce critère peut être donné en début.

proc sql;
   select sex, case max(age)
                 when (13) then ’13’
                 else ‘N/A’
               end as max_age2
   from sashelp.class
   group by sex;
quit;

Mais, il est bon de se demander si un format ne serait pas plus adapté dans ce cas.

proc format;
  value max_age
   13    = ’13’
   other = ‘N/A’;
run;

proc sql;
   select sex, put(max(age),max_age.) as max_age2
   from sashelp.class
   group by sex;
quit

2.3 Créer une macro variable

Voici pour terminer un petit exemple où une macro variable POP est crée. Sa valeur dépend de l’âge maximum observé dans le data set.

proc sql; *noprint;
   select case
            when
max(age) > 13 then ‘>13’
            when max(age) >= 0 then ‘[0-13]’
            else ‘N/A’
          end into :pop
   from sashelp.class;
quit;

h1

Penser conditionnel (2/3) : SELECT

juin 26, 2008

Pour dire à SAS quelles actions sont à mener si des critères sont remplis, nous avons vu la syntaxe IF/THEN/ELSE (voir article). Dans un data step, l’alternative à cette syntaxe, SELECT WHEN, fait l’objet du présent article.

1. La syntaxe de base

Toutes les conditions sont englobées entre l’instruction SELECT et l’instruction END.  Chaque condition est introduite par l’instruction WHEN. Les observations non sélectionnées avant la fin sont traités par l’instruction OTHERWISE.

A la différence de la syntaxe IF/THEN :

  • Les conditions sont listées entre parenthèses et aucun mot-clé n’introduit l’action.
  • Si toutes les conditions se basent sur une seule variable, celle-ci peut-être citée une seule fois et ce en tout début dans l’instruction SELECT. Mais il faut aussi que les valeurs prises par la variable soient toutes listées. Ainsi <5 ne marche pas mais 0,1,2,3,4 marche.

De la même manière que IF/THEN :

  • Seuls les records non sélectionnés pas un précédent WHEN sont considérées par les conditions suivantes. C’est le même principe que le ELSE IF.
  • Si plusieurs actions sont planifiées, celles-ci sont listées entre un DO et un END.

select  <nom_variable, optionnel> ;
when (<condition>)
do;
<action 1>;
<action 2>;
*etc;
end;
when (<condition>)  <action>;
otherwise <action>;
end;

2. Le caractère unique du SELECT WHEN

Pas d’action s’il vous plaît : Lorsqu’il n’y a aucune action pour une condition donnée, il est possible d’écrire une instruction WHEN sans donner de détails après la parenthèse. On parle d’instruction nulle.

OTHERWISE est parfois obligatoire : Si aucune condition n’est rempli pour un data set donné, il est important d’avoir une instruction OTHERWISE. Celle-ci peut rester vide d’action.

3. Illustration par un exemple

Premier exemple : les trois caractéristiques de ce premier exemple sont les suivantes.

  • La condition est basée sur une seule variable. On choisit dont de nommer une seule fois cette variable dans l’instruction SELECT.
  • Il y a plusieurs actions (DO/END) pour certaines conditions.
  • Dans le cas où aucune des conditions précédentes ne serait remplie, l’instruction OTHERWISE est ajoutée.

Les records incluant un âge manquant sont sauvegardées dans le data set nommé MISS_AGE et la  date de création d’une requête (query) pour clarifier le record est ajoutée dans une variable QUERY_SDT (Query Starting Date). Les autres records, traitant des moins de 5 ans, sont sauvegardés dans le data set YOUNG.

data miss_age young ;
set sashelp.class;
select (age);
when (.)
do;
query_sdt=mdy(3,26,2008);
output miss_age;
end;
when (0,1,2,3,4) output young;
otherwise;
end;
run;

Second exemple : cet exemple se distingue sur trois aspects.

  • La condition est basée sur plusieurs variables. Il faut dont les lister à chaque nouvelle instruction WHEN.
  • Une seule action n’est donnée à chaque fois voir moins. L’action porte sur la valeur de la variable POP. Il n’y a pas d’action quand l’âge n’est pas une valeur connue ou que le sexe n’est pas défini par les lettres majuscules F (female) ou M (male).
  • Les valeurs restantes se rapportent aux hommes ayant une valeur pour leur âge. C’est notre troisième population.

data pop;
set sashelp.class;
select;
when (age > 13 and sex=‘F’) pop = 1;
when (age >= 0 and sex=‘F’) pop = 2;
when (age < 0 or sex not in (‘F’,‘M’));
otherwise pop = 3;
end;
run;

A dans huit jours pour une présentation du CASE WHEN de la procédure SQL.

h1

Penser conditionnel (1/3) : La base du IF

juin 19, 2008

Selon que des variables aient certaines valeurs ou non, le programmeur peut décider de créer une nouvelle variable, extraire une ligne d’observation, etc.

SAS propose plusieurs syntaxes pour exprimer ces conditions.

  • Dans le data step et la procédure SQL, pour extraire un sous ensemble de records sans autre action le WHERE est probablement le plus adapté. De plus, dans d’autres cas que le data step et la PROC SQL l’option WHERE est aussi utilisable (PROC SORT, PROC FREQ, ODS OUTPUT…).
  • Sinon, dans un data step, on rencontre le IF et le SELECT et dans une procédure SQL, CASE WHEN est disponible.

Ce sujet sera divisé en 3 articles à commencer par la syntaxe du IF. Dans huit jours, le prochain rendez-vous sera consacré au SELECT. Enfin le dernier article de la série s’intéressera au CASE WHEN.

1. Le minimum ou presque

« S’il pleut, alors je prend mon parapluie, sinon, je le laisse au bureau. » Dans cette phrase, on repère trois mots : si, alors, sinon. Traduisez par IF, THEN, ELSE. C’est trois mots, version anglaise, forme la syntaxe de base.

Dans l’exemple suivant, on considère les variables AGE et SEX pour créer la variable PP_NY (per protocol population, no/yes) : « Si ma variable âge est supérieure à 13 et qu’il s’agit d’hommes alors ma variable pp_ny=1, sinon pp_ny=0. »

data class;
set sashelp.class;
if age > 13 and sex=‘M’ then pp_ny=1;
else pp_ny=0;
run;

On remarquera l’usage de l’instruction finale ELSE pour inclure tous les cas non pris en compte précédemment.

2. Multiplier les combinaisons

Dans ce second exemple, une instruction ELSE IF a été ajoutée. Ainsi tous les hommes de 13 ans ou moins pour lesquels on connaît l’âge sont sélectionnés dans cette seconde instruction. Enfin, les valeurs restantes correspondent aux lignes d’observations où l’âge est manquant ou concernant les femmes.

data class;
set sashelp.class;
if age > 13 and sex=‘M’ then pp_ny=1;
else if age > .z and sex=‘M’ then pp_ny=0;
else pp_ny=.;
run;

 

ELSE IF : il est préférable d’utiliser le ELSE IF, plutôt que le IF pour des raisons de performance et pour éviter des erreurs d’étourderie.

  • Par performance j’entends : seules les observations qui ne sont pas valides dans la première condition sont lues pour évaluer la condition suivante. C’est un temps très précieux quand on traite une grosse base de données.
  • Par erreur j’entends : en aucun cas, des observations peuvent-être sélectionnées par deux instructions. Ainsi si PP_NY=1, il n’y a aucune chance qu’il devienne PP_NY=0 après exécution de la seconde instruction.

Important : dans l’exemple précédent, j’ai volontairement choisi de lister plus d’une variable pour définir ma condition. En effet, si vous avez une seule variable en entrée et une seule variable en sortie, un informat suffit. Plusieurs avantages se cachent derrière :

  • le programme est allégé
  • l’accès aux valeurs est plus évident puisque les formats font partie des informations données en début de programme.

Voici ce que cela donnerait si on ne considérerait que la variable AGE pour définir la variable PP_NY.

proc format;
   invalue age_pp
   ._.z    = .
low-13   = 0
   13
<-high = 1;
run;

data class;
   set sashelp.class;
pp_ny=input(age,age_pp.);
run;

3. Parenthèse sur les valeurs manquantes 

On a fait très attention de ne pas inclure les âges manquants pour définir PP_NY=1/0. La valeur .z est une valeur manquante spéciale « special missing ». SAS en compte 27.

L’intérêt des valeurs manquantes spéciales : le but des special missings est d’offrir d’un éventail de valeurs pour distinguer les valeurs manquantes. Prenez le cas d’une variable indiquant le contraceptif médicamenteux pris par le patient. S’il s’agit d’une femme et que l’information n’est pas fournie, on mettra manquant (un point). Par contre, s’il s’agit d’un homme, on marquera .A pour « non applicable ». Un format permettra ensuite de représenter . par MISSING et .A par N/A.

L’ordre des valeurs manquantes : l’ordre des missings et special missings est important à connaître. Cela vous expliquera pourquoi j’ai utiliser .z et non . dans l’exemple précédent. Vous pouvez vous reporter à la Online Doc : Missing Values. En résumé cela donne :

  • ._ pour le plus petit,
  • . juste après,
  • .A
  • .Z pour le plus grand des special missings
  • valeurs négatives
  • valeurs positives

Alternative avec la fonction MISSING : sachez qu’une autre solution pour exclure toutes les valeurs manquantes (missing et special missing), c’est d’utiliser la fonction MISSING qui a pour autre avantage de s’appliquer autant aux valeurs textes qu’aux valeurs numériques. C’est très pratique quand on ne connaît pas à l’avance le type de la variable. Dans la PROC SQL, WHERE… il y a aussi « WHERE x IS MISSING ».

4. Plusieurs actions quand une condition est remplie (DO-END)

Si une condition est remplie, il peut s’avérer nécessaire de faire plusieurs choses. Par exemple, on peut à la fois créer une nouvelle variable et sortir la ligne d’observations.

Dans l’exemple ci-dessous, la variable SEX ne prend que les valeurs ‘M’ et ‘F’. Dans ce cas précis, au final, il y a plus de records à la fin. Tout d’abord, tous les records sont extraits et POP est défini comme étant égal à 1. Ensuite, pour les records masculins, les records sont sortis une deuxième fois et notre variable POP est alors égale à 2.

data class;
set sashelp.class;
pop=1;
output;
if sex=‘M’ then
do;
pop=2;
output;
end;
run;