Archive for the ‘Data Management’ Category

h1

Valeur formatée utilisée pour définir la macro variable. Attention !

janvier 11, 2010

Vous imaginez qu’un format ne sert qu’à l’affichage des données et que lorsque vous faîtes une opérations sur les données vous travaillez sur les données brutes. Et pourtant, avec les macro variables vous pouvez avoir des surprises. Démonstration.

1. L’exemple qui marche comme prévu

Dans un premier temps, le data set (ONE) est créé. Il a une variable numérique x. Dans ce data set, il n’y a qu’une observation x=123456789012 soit une seule valeur composée de 12 chiffres. Un format 12. est appliqué à la variable.

data one;
x=123456789012;
format x 12.;
run;

Dans un second temps une macro variable est créée.

proc sql;
select x into : x
from one;
quit;

Dans un troisième temps,ne sont sélectionnées que les observations où x=123456789012.

data two;
set one (where=(x=&x.));
run;

Le data set TWO a alors toujours une observation.

2. Le détail qui fait la différence

Maintenant enlevé le format permanent 12. ou mettez à la place un format x8.

data one;
x=123456789012;
*format x 12.;
format x 8.;
run;

C’est la valeur formatée de x qui est sauvegardée dans la macro variable et non la valeur interne. Comme un format de 8. ne suffit pas pour afficher l’intégralité du nombre, la valeur est transformée et ne peut plus être précisément égale à la valeur initiale. Donc attention !

proc sql;
select x into : x
from one;
quit;

Cette fois-ci, la seule observation de data set est perdue.

data two;
set one (where=(x=&x.));
run;

h1

Plusieurs mots d’un paramètre de macro à mettre entre guillemets (%QSYSFUNC, %STR(), TRANWRD)

mai 28, 2009

Mettre entre guillemets les mots contenus dans une macro variable SAS et les séparer par des virgules est possible au moyen des fonction %STR(), %QSYSFUNC et TRANWRD. Dans quel cas est-ce utile ? Comment se décompose cette syntaxe ?

1. Dans quel cas a-t-on besoin d’ajouter des guillemets et virgules ?

Lors de l’écriture d’une macro, vous pouvez avoir besoin d’autoriser plus d’un mot dans un des paramètres.

options mprint;

%macro test (multival=);

%mend test;

%test (multival=Alfred William);

Note : l’option MPRINT de l’instruction OPTIONS permettra de voir la résolution de la macro dans la log.

Ensuite, le contenu de ce paramètre traité comme une macro variable peut être appelé dans une condition. Dans l’exemple qui suit « Alfred », »William » sera remplacée par la macro variable mise à jour.

proc print data=sashelp.class (where=(name = (« Alfred », »William »));

run;

Il faut pour cela mettre la macro variable à jour en ajoutant des guillemets et la virgule comme séparateur.

2. Comment ajouter guillemets et virgules ?

2.1 Un mot

Dans le cas d’un paramètre avec un mot, on peut ajouter %str(% ») devant et derrière. Le symbole % permet d’introduire les caractères spéciaux comme le guillemet.

%let multival=%str(% »)&multival.%str(% »);

La macro donne alors :

%macro test (multival=);

%let multival=%str(% »)&multival.%str(% »);

proc print data=sashelp.class (where=(name = &multival.));

run;

%mend test;

%test (multival=Alfred);

2.2 Plus d’un mot

Pour mettre entre guillemets plus d’un mot, l’espace entre les mots sera remplacé par « , » (guillemet, virgule, guillemet) au moyen de la fonction TRANWRD.

%qsysfunc(tranwrd(&multival.,%str( ),%str(% »,% »)))

Pour exécuter cette fonction, qui n’a pas d’équivalent dans les macros fonctions, il faut englober le tout dans %SYSFUNC/%QSYSFUNC. La présence de la virgule oblige dans notre cas à utiliser %QSYSFUNC.

%macro test (multival=);

%let multival=%str(% »)%qsysfunc(tranwrd(&multival.,%str( ),%str(% »,% »)))%str(% »);

proc print data=sashelp.class (where=(name in (&multival.));

run;

%mend test;

%test (multival=Alfred William);

2.3 Plus d’un mot mis en majuscule

Enfin, pour ne pas tenir compte de la case, le texte peut être mis en majuscule au moyen de la fonction %UPCASE.

where=(upcase(name) in (%upcase(&multival.))

Cela donne :

%macro test (multival=);

%let multival=%str(% »)%qsysfunc(tranwrd(&multival.,%str( ),%str(% »,% »)))%str(% »);

proc print data=sashelp.class (where=(upcase(name) in (%upcase(&multival.))));

run;

%mend test;

%test (multival=Alfred William);

Lectures complémentaires

h1

Enlever les balises HTML d’un texte (do while et do until)

mai 18, 2009

Les balises HTML sont des mots entourés de < et > servant à la mise en forme de pages Internet. Dans l’exemple qui suit le but est d’enlever avec SAS des balises HTML contenues dans une variable appelée DESCRIP au moyen d’une boucle.  Cet exemple, basé sur un cas réel, permettra d’illustrer la syntaxe de DO UNTIL et de DO WHILE.

1. La fonction SUBSTR pour enlever un symbole <…>

Pour enlever une balise, je choisis ici de remplacer la chaîne commencant par < et se terminannat par > au moyen de la fonction SUBSTR. Pour ce faire,

  • paramètre 1 : donner le nom de la variable en premier
  • paramètre 2 : préciser la position du symbole < en second 
  • paramètre 3 : donner la longueur du texte en calculant le nombre de caractères entre ce symbole de début de balise et celui de fin (position de su symbole de fin > – position du symbole de début < + 1).

data no_tag (drop=tag:);
   descrip=‘<p>my text</p>’;
   tag_start = index(descrip,‘<‘);
   tag_end   = index(descrip,‘>’);
   substr(descrip,tag_start,tag_end-tag_start+1)=‘ ‘;
run;

Ici le texte à mettre à jour est <p>my text</p>. Cette première étape data remplace la première balise et seulement la première. Pour des raisons de lisibilité, j’ai choisi de créer deux variables intermédiaires qui retourne la position de < (variable TAG_START) et de > (TAG_END) au moyen de la fonction INDEX.

En fin d’étape data, toutes les variables dont le nom commence par TAG sont supprimée grâce à l’option DROP.

2. Répéter l’opération au moyen d’une boucle DO UNTIL

A chaque exécution de la boucle la variable DESCRIP est mise à jour : une balise <…> est enlevée.

La boucle sera exécutée jusqu’à ce qu’aucun symbole < ne soit identifié. En d’autres termes, la boucle sera exécutée jusqu’à ce que la fonction INDEX retourne la valeur zéro.

data no_tag (drop=tag:);
   descrip=‘<p>my text</p>’;
   do until(index(descrip,‘<‘)=0);
      tag_start = index(descrip,‘<‘);
      tag_end   = index(descrip,‘>’);
      substr(descrip,tag_start,tag_end-tag_start+1)=’ ‘;
   end;
run;

3. Répéter l’opération au moyen d’une boucle DO WHILE

A chaque exécution de la boucle la variable DESCRIP est mise à jour : une balise <…> est enlevée.

La boucle sera exécutée tant qu’un symbole < sera identifié. En d’autres termes, la boucle sera exécutée tant que la fonction INDEX ne retournera pas la valeur zéro.

data no_tag (drop=tag:);
   descrip=‘<p>my text</p>’;
   do while(index(descrip,‘<‘) ne 0);
      tag_start = index(descrip,‘<‘);
      tag_end = index(descrip,‘>’);
      substr(descrip,tag_start,tag_end-tag_start+1)=‘ ‘;
   end;
run;

Avec DO UNTIL et DO WHILE, il faut faire attention aux boucles infinies. Si la condition pour sortir de la boucle n’est jamais obtenue. L’exécution continue sans fin.

Lectures complémentaires

Sur le blog www.sasreference.fr

Online Doc

  • DO WHILE Statement
  • DO UNTIL Statement
h1

Un premier exemple d’array : changer toutes les variables 1/2 en variable 0/1

mai 11, 2009

Imaginez que vous avez dans une table des variables oui/non où 1 représente non et 2 représente oui. Changement de standard oblige, vous devez symboliser les non par un 0 et les oui par un 1.

Si mavariable=1 alors mavariable=0.
Sinon mavariable=1.

Bien sûr, vous pouvez traiter séparément chaque variable. Ce chantier laborieux est remplaçable par une boucle où seul le nom de la variable change à chaque fois. Vous voulez donc effectuer une même opération sur un grand nombre de variables. La syntaxe de l’array est faite pour vous.

1. Un data set pour l’exemple

Voici la table (SAS data set) utilisée pour l’exemple. Elle s’appelle FINAL. Elle est composée d’une variable caractère et de trois variables numériques, toutes des variables binaires de type oui (2)/ non (1).

data final;
input subject $ pregny validny aeny;
datalines;
A 1 2 1
B 1 1 2
C 2 1 2
D 1 2 2
;
run;

Le but sera d’obtenir un data set avec des variables binaires de type oui (1)/ non (0).

subject pregny validny aeny;
A      0       1      0
B      0       0      1
C      1       0      1
D      0       1      1

2. C’est quoi un array ?

Un array est un nom qui désigne une liste de variables. Il est propre à l’étape data.

  • Définir un nouvel array : Dans un premier temps, l’array est à créer: Sous un nom de son choix, sont sauvegardés sauvegarde des noms de variables (les éléments de l’array) dont l’ordre est indexé pour pouvoir les désigner de manière individuelle par la suite.
  • Appler les variables contenues dans l’array : Dans un second temps, chaque élément de l’array (chaque variable) est appelé/désigné, non pas par son nom, mais par sa position dans l’array.

3. Définir un array

Pour définir un array, il existe l’instruction ARRAY. Elle est composée de trois parties principales et d’un quatrième optionnel.

  • le nom de l’array
  • le nombre de variables  listées (le nombre d’éléments dans l’array)
  • le nom des variables
  • la valeur des variables (optionel)

Dans l’exemple, j’ai un array nommé NY composé de trois éléments : les variables PREGNY (prenant no/yes), VALIDNY (valid no/yes) et AENY (adverse event no/yes).

data final;
set final;
*array ny {1998:2000} pregny validny aeny;
*array ny {1:3} pregny validny aeny;
array ny {*} pregny validny aeny;
run;

Je vous propose trois alternatives pour la notation. Ma préférence, pour des raisons de simplicité dans ce cas, va au cas numéro trois.

  • {1998:2000} Dans le premier cas, la variable PREGNY a pour référence la position 1998, VALIDNY a pour référence la position 1999 et la variable AENY est en position 2000.
  • {1:3} Dans le second cas, la numérotation commence à 1 avec la variable PREGNY et se termine à 3 avec la variable AENY.
  • {*} Dans le troisième et dernier cas, la numérotation est implicite. Comme précédemment. Elle ira de 1 à 3. SAS se charge de compter le nombre de variables pour savoir la dimension de l’array. Si SAS fait le travail pour nous, pourquoi se priver de ce luxe !

Note : La première syntaxe peut apporter dans certains cas un plus en terme de compréhension. C’est le cas quand le numéro a un lien avec le sens de la variable. Par exemple, les variables RESULT98, RESULT99 et RESULT00 peuvent avoir les positions 1998, 1999 et 2000 et donc avoir un caractère informatif.

4. Appeler un array

Pour appeler un élément d’un array (une variable), il faut donner le nom de l’array suivi de la position de la variable dans l’array. Ainsi :

  • ny{1} désigne la variable PREGNY
  • ny{2} fait référence à la variable VALIDNY
  • ny{3} concerne la variable AENY

data final;
set final;
array ny {*} pregny validny aeny;
*variable PREGNY;
if ny{1}=1 then ny{1}=0;
else ny{1}=1;
*variable VALIDNY;
if ny{2}=1 then ny{2}=0;
else ny{2}=1;

*variable AENY;
if ny{3}=1 then ny{3}=0;
else ny{3}=1;

run;

L’intérêt de cette notation vient dans l’usage d’une boucle où la position de la variable sera automatiquement changé.

data final;
set final;
array ny {*} pregny validny aeny;
do i=1 to dim(ny)
;*do i=1 to 3;
if ny{i}=1 then ny{i}=0;
else ny{i}=1;
end;
run;

Pour les plus paresseux comme moi, on demandera à SAS de calculer le nombre d’éléments contenus dans l’array (la dimension) au moyen de la fonction SAS propre à l’array DIM().

Je vous proposerai dans les semaines à venir un autre article sur les subtilités de l’array.

h1

Récupérer la valeur d’une option système dans une macro variable, %SYSFUNC(GETOPTION())

avril 30, 2009

Les options SAS modifiables au moyen de l’instruction globale OPTIONS peuvent être retrouvées dans une étape data ou autre au moyen de %SYSFUNC(GETOPTION()).

Par exemple, cette semaine, j’ai eu besoin de savoir combien de caractères par ligne je pouvais entrer dans ma sortie (fenêtre OUTPUT). En d’autres termes, je voulais connaître la LINESIZE et en fonction d’elle ajuster les colonnes de mon listing généré au moyen d’un simple PROC REPORT.

1. Lire dans la LOG l’information

L’instruction PROC OPTIONS permet de lister toutes les options dans la fenêtre LOG de SAS. En ajoutant OPTION=, l’affichage est réduit à la seule option LINESIZE.

proc options option=linesize;
run;

Dans notre exemple, l’option LINESIZE est de 91. Jusqu’à 91 caractères pourront être affichés sur une même ligne avec un PROC PRINT ou autre.

LINESIZE=91 Line size for SAS log and SAS procedure output
NOTE: PROCEDURE OPTIONS used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

2. Sauvegarder l’information dans une macro variable

Pour illustrer la syntaxe %SYSFUNC(GETOPTION()), je choisi de sauvegarder l’information dans une macro variable appelée CURRENT_LS. Cette valeur est ensuite affichée dans la LOG au moyen de l’instruction %PUT.

%let current_ls=%sysfunc(getoption(linesize));
%put &current_ls.;

Vous pouvez directement inclure %SYSFUNC(GETOPTION()), dans une instruction globale comme TITLE si vous le souhaitez.

La liste des options du système SAS est grande. A vous d’explorer les possibilités que vous offre cette notation.

h1

Tout sur l’instruction BY

avril 14, 2009

Me rendant compte que l’instruction BY pouvait poser des difficultés lorsqu’on débute avec SAS, j’ai décidé de faire le point sur cette instruction.

1. Une instruction locale

L’instruction BY peut servir dans toutes les étapes data et procédures à l’exception de PROC SQL.

2. Un ordre défini par le nom des variables :

L’instruction BY est suivie du nom des variables servant pour le tri.

Dans un premier temps, les observations sont triées selon les valeurs de la première variable citée, ici SEX. Puis, pour chacune des valeurs prises par SEX (M et F), les données sont triées par NAME.

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

3. PROC SORT : le premier usage de l’instruction BY : L’instruction BY est logiquement obligatoire dans un PROC SORT. Sinon SAS ne saurait pas dans quel ordre trier les données. Le mot DESCENDING peut-être ajouté pour préciser un ordre décroissant. Ici les données sont d’abord triées par SEX puis par nom en ordre descendant.

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

L’autre manière de trier les données est d’utiliser la procédure PROC SQL.

Idée : Vous aurez souvent un PROC SORT avant d’utiliser l’instruction BY dans une autre procédure ou étape data. Simplifiez-vous la vie en copiant l’insstruction au niveau du PROC SORT et en la collant au niveau de la procédure ou étape data suivante.

4. SAS vous informe si les données ne sont pas triées comme indiqué

L’instruction BY précise à SAS dans quel ordre les données doivent être lues. Si les données ne respectent pas cet ordre, SAS s’arrête et fourni un message d’erreur.

5. L’instruction BY : obligatoire ou optionnelle ?

L’instruction BY est optionelle dans une instruction SET. Utilisée pour empiler les données de deux data sets, elle permettra d’intercaler les observations des deux sources selon leur valeurs au lieu de mettre d’abord toutes les observations du premier data set cité et ensuite toutes les observations du second data set.

L’instruction BY reste pratiquement indispensable avec MERGE puisqu’elle sert à relier les observations de deux data sets par les variables du même nom. Sans elle, les observations du second data set pour les variables du même nom réécrirait sur celle du premier.

L’instruction BY est indispensable avec FIRST et LAST.

6. D’autres usages de l’instruction BY

L’instruction BY peut s’ajouter dans un PROC REPORT. Une option NOBYLINE permettra de changer le titre à chaque nouvelle combinaison de valeurs désignée par l’instruction. Néanmoins la mise à jour du titre par cette approche avec ODS RTF par exemple ne fonctionne pas.

L’instruction BY peut servir dans toutes less procédures (sauf PROC SQL) et notamment dans les procédures statistiques. Voir dans les lectures complémentaire l’usage de l’instruction BY avec PROC FREQ.

Lectures Complémentaires

SAS Online Doc

  • BY-Group Processing in SAS Programs
h1

Evaluer le critère performance TEMPS d’un programme (%SYSFUNC, %SYSEVALF)

avril 10, 2009

Un critère pour évaluer la performance d’un programme est de connaître son temps d’exécution. La fonction système %SYSFUNC permettra de récupérer le temps à un instant donné et la fonction  %SYSEVALF servira à calculer la différence entre deux temps pré-enregistrés. Voici un exemple en 4 étapes.

1. Récupérer le temps en début de programme

Dans un premier temps, le temps de début est sauvegardé dans une macro variable TEMPS_DEBUT. Il est extrait au moyen de la fonction TIME() et est donc exprimé en secondes.

%let temps_debut = %sysfunc(time());

2. Exécuter la partie principale du programme

Pour l’exemple un simple PROC PRINT est ajouté comme partie principale du programme.

proc print data=sashelp.class;
run;

3. Récupérer le temps en fin de programme

Dans un troisième temps, le temps en fin de programme est sauvagardé dans la macro variable TEMPS_FIN. Comme précédemment; la fonction TIME() est utilisée.

%let temps_fin = %sysfunc(time());

4. Evalutation et affichage de la durée écoulée

La durée écoulé entre le début et la fin du programme est sauvegardée dans la macro variable DUREE. Cette durée est ensuite affichée dans la log au moyen de l’instruction %PUT.

Sur le même principe qu’une fonction %EVAL dans une macro, la fonction %SYSEVALF permet de considérer les deux variables TEMPS_DEBUT/TEMPS_FIN comme des nombres le temps du calcul de la différence.

%let duree = %sysevalf(&temps_fin.-&temps_debut.);
%put Durée d’exécution : &duree.;

Lectures complémentaires

www.sasreference.fr

SAS Online Doc

  • Using SAS Language Functions in the Data Step and Macro Facility
  • %SYSFUNC and %QSYSFUNC Functions
  • Summary Descriptions and Syntax
  • %EVAL Function
  • %SYSEVALF Function
  • How the macro processor evaluates Arithmetic Expressions
  • TIME Function
h1

Copier une table dans une autre bibliothèque (PROC COPY)

mars 28, 2009

Lors de ses débuts avec SAS, l’étape data est souvent la méthode utilisée pour créer une table (data set) dans une bibliothèque différente de celle d’origine. Cette approche est tout à fait logique lorsque des modifications sont intervenues sur la table. Par contre, dans le cas d’un copier 1/1, la performance est meilleure avec un PROC COPY car les observations ne sont pas lues.

1. Créer une table SAS, une vue SAS et fichier catalogue pour les formats pour l’exemple

Afin de monter les variantes de la procédure PROC COPY, trois types de fichiers (member type) sont créés dans la bibliothèque WORK:

  • une table SAS (data set) nommée DSN
  • une vue (view) nommée VIEW NAME
  • un format catalog nommé FORMATS par défaut et contenant un seul format ici : NY

data dsn;
   x=1;
run;

proc sql;
   create view viewname as
      select *
      from sashelp.class;
quit;

proc format;
   value ny 0=’No’
            1=’Yes’;
run;

2. Copier tous les trois fichiers SAS dans la bibliothèque SASREF

Par défaut, tous les types de fichiers de la bibliothèque WORK sont copiés dans SASREF

libname sasref ‘C:/sasref’;
proc copy in=work out=sasref;
run;
libname sasref;

3. Ajouter de la flexibilité

Pour ajouter de la flexibilité, vous pouvez limiter le choix

  • à un type de fichier : memtype=data, memtype=view ou  memtype=catalog
  • à des noms de fichiers à sélecionner (instruction SELECT) ou à exclure (instruction EXCLUDE)

proc copy in=work out=sasref; *memtype=data;
   *select dsn formats;
   *exclude dsn formats;

run;

Rien ne  vous empêche d’utiliser plusieurs instructions SELECT (ou EXCLUDE) : une par type de fichiers

proc copy in=work out=sasref;
   select dsn     / memtype=data;
   select formats / memtype=catalog;
run;

4. PROC DATASETS alternative à PROC COPY

Développée plus récemment, la procédure PROC COPY englobe les fonctionnalités de plusieurs procédures et est enrichie de commandes qui lui sont propres.

PROC COPY fait partie des fonctionalités de PROC DATASETS. Par défaut, la bibliothèque de la procédure DATASETS est WORK. Pour la modifier au seul niveau de COPY, ajouter IN= dans l’instruction COPY. Cela aura la priorité sur l’option LIBRARY= de l’instruction PROC DATASETS.

proc datasets; * library=work; *memtype=data;
   copy /*in=work*/ out=sasref;
   select dsn     / memtype=data;
   select formats / memtype=catalog;
run;

Lectures complémentaires :

En savoir plus avec la SAS Online Doc :

  • The COPY Procedure
  • The DATASETS Procedure (l’intruction COPY)
  • The DATASETS Procedure for Unix
  • The DATASETS Procedure for Windows
  • The DATASETS Procedure for z/OS
h1

Visualiser le contenu d’un catalogue contenant des formats

mars 9, 2009

Les formats sont sauvegardés dans SAS dans des fichiers appelés catalogues (format catalog). Par défaut, tous les formats envoyés dans une même bibliothèque sont sauvegardés dans le même catalogue. Deux questions se posent après :

  • Comment voir la liste des formats présents dans un catalogue ?
  • Comment retrouver le contenu d’un format en particulier ?

1. Créer deux formats dans la bibliothèque SASREF

Pour illuster les deux points qui suivent, sont créés deux formats dans la fichier FORMATS de la bibliothèque SASREF.

  • Le premier format est nommé CNTRY et s’applique à des pays. Il s’agit d’un format alphanumérique (s’applique à du texte).
  • Le second format NY (No/Yes) est un format numérique.
libname sasref  'C:/sasref';

proc format lib=sasref;
   value $ cntry 'FR' = 'France'
                 'DE' = 'Germany'
                 'UK' = 'United-Kingdom';
   value ny      0    = 'Non'
                 1    = 'Yes';
run;

2. Lister les formats présents dans un catalogue avec PROC CATALOG

La procédure PROC CATALOG a la capacité de lister le nom des formats d’un format catalog.

proc catalog c=sasref.formats;
   contents stat;
run;

3. L’option FMTLIB de PROC FORMAT pour voir le contenu des formats

Pour voir les différentes valeurs prises de tous les formats de SASREF (catalogue FORMATS), l’option FMTLIB est joutée dans une procédure PROC FORMAT.

  • Pour ne sélectionner que certains formats en particulier, l’instruction SELECT est à disposition.
  • Inversement, l’instruction EXCLUDE permet d’ôter certains formats de l’affichage.

Dans les deux cas, il faudra préciser si les formats concernées sont numérique ou alphanumérique en ajoutant le symbole dollar ($) devant le nom de chaque format alphanumérique.

proc format library=sasref.formats fmtlib;
   *select $cntry ny;
   *exclude $cntry ny;
run;

Lectures complémentaires :

h1

Modifier un data set sans le lire (formater, renommer, libeller)

mars 5, 2009

Sous SAS, il est possible d’ajouter et supprimer des formats avec une étape data. Cela implique la lecture des données. Pour s’attaquer aux formats sans lire les données, il y a la procédure PROC DATASETS. Quelle est la syntaxe à soumettre ? Quelles sont les autres modifications possibles ? Tout d’abord, vous trouverez le data set servant d’exemple. Puis, la version classique avec l’étape data est présentée suivie de la syntaxe de PROC DATASETS.

1. Les données servant d’exemple, le data set CLASS

Un data set CLASS : Dans cet exemple, un data set CLASS est créé dans la bibliothèque WORK. Il se base sur le data set du même nom situé dans la bibliothèque SASHELP.

Une variable SEX avec un format : Dans ce data set, on trouve une variable nommée SEX. Un format est appliqué sur cette variable de manière permanente (jusqu’à qu’il soit explicitement supprimé ou jusqu’à ce que le data set soit supprimé).

Un format SEX : Le format est également appelé SEX. Il est créé au préalable dans une procédure PROC FORMAT. Les valeurs ‘M’ apparaissent alors sous la forme ‘Male’ (homme) et les ‘F’ apparaissent sous la forme ‘Female’ (femme).

*create a format called SEX;
proc format;
   value $ sex 'M'='Male'
               'F'='Female';
run;
*Create a data set named CLASS ;
*based on the SASHELP.CLASS data set ;
*adding the SEX format to the SEX variable;
data class;
   set sashelp.class;
   format sex sex.;
run;

2. Solution avec une étape data

Nom du data set final : Dans cette étape data (data step), une table SAS (SAS data set) CLASS1 est créée à partir du data set CLASS.

Un label pour le data set : Un libellé (label) est appliqué sur le data set afin d’enrichir la compréhension globale du nouveau data set. Le libellé est « Changes with a Data Step ».

Renommer une variable : la variable WEIGHT (poids) est renommée. Elle s’appelle à la fin WEIGHT_STONE (poids en stone).

Un label pour une variable : un libellé est ajouté à la variable NAME du data set pour faciliter de nouveau la compréhension, de la variable cette fois. Le libellé est « Student Name ».

Traîter les formats : Enfin, l’instruction FORMAT enlève, dans le cas présent, le format de toutes les variables. Si vous voulez enlever seulement le format associé à la variable SEX, utilisez l’instruction en commentaire. Vous pouvez aussi assigner des formats sur d’autres variables avec une instruction FORMAT.

data class1;
   set class (label='Changes with a Data Step' rename=(weight=weight_stone));
   label name='Student Name';
   format _all_;
   *format sex;
 run;

*View the data step result;
proc print data=class1 label;
run;


3. Solution avec la procédure PROC DATASETS

Nom du data set final, instruction CHANGE : A la différence de l’étape data, ici aucun nouveau data set n’est créé. Le data set d’origine est renommé. En d’autres termes, le data set CLASS n’existe plus en tant que tel. L’instruction CHANGE a servi à faire la manipulation.

Un label pour le data set, instruction MODIFY : Un libellé (label) est appliqué sur le data set au moyen de l’instruction MODIFY. Le libellé est « Changes with PROC DATASETS ».

Renommer une variable, instruction RENAME (+MODIFY) : la variable WEIGHT est renommée WEIGHT_STONE au moyen de l’instruction RENAME après avoir utlisé l’instruction MODIFY.

Un label pour une variable, instruction LABEL (+MODIFY) : l’instruction LABEL utlisée en combinaison avec MODIFY ajouter le libellé « Student Name » à la variable NAME.

Traîter les formats, instruction FORMAT (+MODIFY) : Enfin, l’instruction FORMAT enlève, dans le cas présent, le format de toutes les variables.

proc datasets;
   change class=class2;
   modify class2 (label='Changes with PROC DATASETS');
   rename weight=weight_stone;
   label name='Student Name';
   format _all_;
run;
*View the PROC DATASETS result;
proc print data=class1 label;
run;
h1

Enlever certains caractères spéciaux avec la fonction TRANSLATE

février 23, 2009

Les 256 caractères ASCII (American Standard Code for Information Interchange) comprennent :

  • les lettres de l’alphabet,
  • les chiffres
  • des lettres accentuées propres à certains langues comme le E accent aigüe
  • des caractères non imprimables comme un tabulation, un retour à la ligne ou un espace.

Ils peuvent notamment arriver dans une table suite à l’importation d’un fichier Excel où ils sont présents. En général, la plupart de ces caractères spéciaux ne sont pas désirés.

Quels sont ces caractères et comment les éliminer ?

1. Quels sont les 34 caractères non imprimables ?

Les caractères ASCII sont numérotés :

  • de 0 à 256 (valeur décimale)
  • de 00 à FF (valeur hexadécimal)
  • Unicode

Les 33 premiers caractères (0 à 32) et le caractère 127 sont forment les caractères non imprimables.

 DEC HEX  Description
  0   00   NUL Null
  1   01   STX Start of Header
  2   02   SOT Start of Text
  3   03   ETX End of Text
  4   04   EOT End of Transmission
  5   05   ENQ Enquiry
  6   06   ACK Acknowledge
  7   07   BEL Bell
  8   08   BS BackSpace
  9   09   HT Horizontal Tabulation
 10   0A   LF Line Feed
 11   0B   VT Vertical Tabulation
 12   0C   FF Form Feed
 13   0D   CR Carriage Return
 14   0E   SO Shift Out
 15   0F   SI Shift In
 16   10   DLE Data Link Escape
 17   11   DC1 Device Control 1 (XON)
 18   12   DC2 Device Control 2
 19   13   DC3 Device Control 3 (XOFF)
 20   14   DC4 Device Control 4
 21   15   NAK Negative acknowledge
 22   16   SYN Synchronous Idle
 23   17   ETB End of Transmission Block
 24   18   CAN Cancel
 25   19   EM End of Medium
 26   1A   SUB Substitute
 27   1B   ESC Escape
 28   1C   FS File Separator
 29   1D   GS Group Separator
 30   1E   RS Record Separator
 31   1F   US Unit Separator
 32   20   [Space] Space
127   7F   DEL Delete

Source : ascii-table.com

2. Un exemple, le symbole « Line Feed »

L’image ci-dessous présent une feuille Excel. La cellule A1 contient un passage à la ligne. Celui-ci indique la présence du caractère spéciale 0A (valeur hexadécimale).

hexadecimal_fr

Après la création d’une table SAS à partir d’un PROC IMPORT, cela donne un petit carré qui ne s’imprimera pas.

hexa_sas_fr

2. Comment éliminer des caractères spéciaux?

En fait, deux choix se présentent :

  • soit vous éliminez les caractères spéciaux,
  • soit vous les remplacez par des blancs

Dans les deux cas, la fonction TRANSLATE peut servir.

Créer le data set pour l’exemple :

data sasref;
   f1=cat('Partie1','0A'x,'Partie2');
run;

Enlever le caractères spécial spécial grâce à la fonction TRANSLATE : la fonction TRANSLATE est composée de trois paramètres : le texte d’origine, les nouveaux caractères et les caractères à remplacer.

data sasref;
   set sasref;
   f2=translate(f1,' ','0A'x);
run;

Le résultat : J’ai choisi de créer une nouvelle variable F2 afin d’afficher simultanément le texte avant et le texte après.

hexa_sas_apres

La différence entre les fonctions TRANSLATE et TRANWRD :

  • A la différence de la fonction TRANWRD, chacune des lettres est remplacée et non des mots.
  • De plus, ici les caractères à remplacer sont cités en dernier (3ème paramètre de la fonction TRANSLATE). Tandis que TRANWRD commence par eux (2ème paramètre de la fonction TRANWRD).

Remplacer plus d’un caractère  : vous pouvez lister autant de caractères hexadécimaux dans le troisième paramètre de la fonction TRANSLATE.

Ici, SAS remplacera les dix premiers caractères ASCII numérotés 00, 01, 02,…09, 0A, s’ils existent, pas un espace.

data sasref;
   set sasref;
   f2=translate(f1,' ','000102030405060708090A'x);
run;

Lectures complémentaires :

Annexe :

Reproduire le fichier Excel : Dans Word, tapez le texte en ajoutant un passage à la ligne. Copiez ensuite ce texte dans au niveau de la base fonction (fx).

Importer le fichier Excel dans SAS :

proc import file='C:/sasref/hexa.xls'
            out=sasref
	   replace;
	   getnames=no;
run;


				
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;
h1

Remplacer un mot par un autre : la fonction TRANWRD

février 10, 2009

La fonction TRANWRD (entendez par là Translate Word) de SAS sert à remplacer un mot par un autre. Quelle est la syntaxe de base ? Quelles sont ses particularités ? A quoi faut-il faire attention lorsqu’on l’utilise ?

1. Le test

data one;
  x='AbcDeffeDGhiDefDEF';
  y1=tranwrd(x,'Def','ZZ');
  length y2 $18;
  y2=tranwrd(x,'Def','ZZZZ');
run;

Voir le data set ONE :

         x                    y1                   y2

AbcDeffeDGhiDefDEF    AbcZZfeDGhiZZDEF    AbcZZZZfeDGhiZZZZD

2. La syntaxe de base

La fonction TRANWRD est composée de 3 paramètres :

  • Le texte d’origine : une variable caractère ou une chaîne de caractères entre guillemets.
  • Le texte à remplacer
  • Le nouveau texte

Note : Les paramètres caractères d’origine et nouveau texte sont inversés dans la fonction TRANSLATE.

3. Les particularités de la fonction TRANWRD

Remplacer un mot : dans l’exemple, ce ne sont par les lettres D, e et f qui sont remplacées mais bien le mot ‘Def’. C’est pour cela que le texte ‘feD’ reste intacte.

Sensible à la case : dans l’exemple, le texte ‘DEF’ n’est pas remplacé car ‘E’ et ‘F’ sont en majuscule. Seul le texte ‘Def’ est changé.

Un nouveau mot de longueur différente : dans l’exemple,

  • Un texte plus court : la variable Y1 voit le mot ‘Def’ composé de trois lettres remplacé par le mot plus court ‘ZZ’ sans blanc à la suite
  • Un texte plus long : le mot ‘Def’ remplacé par un mot plus long ‘ZZZZ’ et donne la variable Y2. Le texte qui suit est tout simplement décalé pour donner la place nécessaire.

4. Redéfinir les longueurs si nécessaire

Si votre nouveau texte est plus long que votre ancien texte, il est important de vérifier que la longueur de la variable est suffisante pour que l’intégralité de la chaîne de caractères soit conservée. Ici, la variable Y2 a une longueur de 18. Deux ‘Def’ sont replacés en ‘ZZZZ’. Il manque la place à deux caractères. Les E et F de fin sont tronqués.

En savoir plus : TRANWRD function (SAS Online Doc)

Un exemple d’utilisation de la fonction TRANWRD : « Afficher 7h30 sous la forme 07:30« .

h1

Deux réponses possibles avec la fonction IFN

janvier 19, 2009

Les fonctions IFN et IFC existent depuis la version 9.1 de SAS. Elles permettent de retourner une valeur si une condition est remplie et une autre si ce n’est pas le cas. Je vous propose d’illustrer la fonction IFN en combinaison avec la fonction LAG.

1. La différence entre les fonctions IFN et IFC

La fonction IFN retourne une valeur numérique alors que la fonction IFC retourne une valeur caractère.

2. Trois paramètres obligatoires pour ces fonctions et un optionnel

Dans un premier temps, il s’agit de définir une condition.

  • Paramètre 1 : définir la condition

Dans un second temps, on assigne chacune des valeurs prises par la nouvelle variable selon que

  • Paramètre 2 : valeur si la condition est remplit,
  • Paramètre 3 : valeur si la condition n’est pas remplit
  • Paramètre 4 : valeur si la condition donne une valeur manquante (optionnel).

3. L’exemple

Dans cet exemple, on a trois variables : PATIENT_ID et CNTRY_ID sont les variables clés. STRT_DT est la date de début d’un effet secondaire.

data adverse_events;
   input patient_id cntry_id $ strt_dt;
   informat strt_dt date9.;
   datalines;
999 DE 03MAR2004
999 DE 04MAR2004
999 DE 06MAR2004
111 AU 12DEC2003
111 AU 15DEC2003
;
run;

On souhaite créer une nouvelle variable contenant la date précédente par patient.

patient_id cntry_id  strt_dt    prev_dt

    999       DE    03MAR2004       .
    999       DE    04MAR2004   03MAR2004
    999       DE    06MAR2004   04MAR2004
    111       AU    12DEC2003       .
    111       AU    15DEC2003   12DEC2004

La solution classique serait d’utiliser un FIRST qui implique que les données soient triées au préalable par patient.

proc sort data=adverse_events;
   by patient_id cntry_id;
run;

data adverse_events;
   set adverse_events;
   by patient_id cntry_id;
   prev_dt=lag(strt_dt);
   first.cntry_id then prev_dt=.;
run;

Mais maintenant qu’on a la fonction IFN, la démarche est plus rapide. Dans notre exemple, seuls les trois paramètres obligatoires de la fonction IFN sont utilisés.

data adverse_events;
   set adverse_events;
   prev_dt=ifn(patient_id=lag(patient_id) and cntry_id=lag(cntry_id),
               lag(strt_dt),
               .);
run;

4. Liens

La fonction LAG

h1

Additionner deux macros variables, la fonction %EVAL

janvier 15, 2009

En langage macro sous SAS, la distinction entre les macro variables numériques et les macros variables caractères n’est pas faite. En fait, toutes les macros variables sont de type caractère. Du coup, comment faire l’addition de deux macros variables contenant des nombres ?

1. La fonction %EVAL

La fonction %EVAL indique à SAS de gérer les indications qu’elles contient comme une opération mathématique. Il est alors possible de faire la soustraction, l’addition, la multiplication et la division de n’importe quelle macro variable contenant des nombres.

2. Deux data sets pour l’exemples : PATH_AE et PATH_PID

Pour illustrer cette macro fonction très simple du langage de programmation SAS, je vous propose ce petit exemple. A la base, il y a deux data sets :

  • PATH_AE (AE: Adverse Events ou effets secondaires) et
  • PATH_PID (PID: Patient Identifier ou identifiant du patient).

Chacun des deux data sets a une variable les chemins d’accès à des répertoires contenant respectivement les fichiers AE et PID. C’est le genre de data set qu’on peut obtenir à partir d’une commande Unix et une étape data.

Combien d’observations dans chaque data set ? : Le data set PATH_AE contient deux observations et le data set PATH_PID en a trois. Vous pouver activer les conditions WHERE pour que chacun des data sets soient vides et ainsi voir le changement qu’il implique dans la suite du programme.

data path_ae ;*(where=(substr(path_ae,1,1) ne 'c'));
   length path_ae $200;
   input path_ae;
   datalines;
c:/project_d15/study145
c:/project_d66/study234
;
run;

data path_pid ;*(where=(substr(path_ae,1,1) ne 'c'));
   length path_pid $200;
   input path_pid;
   datalines;
c:/project_a99/study133
c:/project_a99/study532
c:/project_b01/study012
;
run;

3. Créer des macros variables

Le code qui suit extrait le nombre d’observations de chacun de nos data sets dans des macro variables. C’est une approche alternative à l’utilisation des dictionnaires qui a le mérite de pouvoir indifféremment extraire des données au niveau du data set qu’au niveau des variables.

La macro variable CNT_AE

  1. Ouvrir le data set PATH_AE de la bibliothèque WORK.
  2. Y extraire le nombre total d’observations et le sauvegarder dans la macro variable CNT_AE.
  3. Fermer le data set PATH_AE.
%let dsid_ae = %sysfunc(open(work.path_ae,in));
%let cnt_ae = %sysfunc(attrn(&dsid_ae.,nobs));
%let rc_ae   = %sysfunc(close(&dsid_ae.));

La macro variable CNT_PID : de manière similaire, le nombre d’observations contenues dans le data set PATH_PID est sauvegardé dans la macro variable CNT_PID.

%let dsid_pid = %sysfunc(open(work.path_ae,in));
%let cnt_pid = %sysfunc(attrn(&dsid_ae.,nobs));
%let rc_pid   = %sysfunc(close(&dsid_ae.));

D’autres %SYSFUNC pourraient au besoin être ajoutées entre l’ouverture et la fermeture du data set.

4. Une petite vérification

A présent, voyons dans la log la valeur prise par la somme des deux macros variables.

%let check= %eval(&cnt_ae.+&cnt_pid.);
%put SASREF Macro Variable Check: &check.;

Si les options WHERE restent en commentaires, CHECK=5 puisque qu’on fait la somme de 2 (observations dans le data set PATH_AE) et 3 (observations dans le data set PATH_PID.

Par contre, si les options WHERE sont inclues, les deux data sets sont vide et CHECK=0.

5. Utiliser la macro fonction %EVAL() dans une macro

Dans le programme suivant, si aucun des deux data sets ne contiennent de données, un message est ajouté dans la log et SAS va directement au point d’encrage donné par PGM_END et donc ici en fin du programme. Tout programme intermédiaire est alors ignoré par SAS.

%macro test;
  *Here additional Program code can be included;
   %if %eval(&cnt_ae.+&cnt_pid.)=0 %then
      %do;
         %put NOTE_TEST_EVAL=--------------------------------;
         %put NOTE_TEST_EVAL= 1. Check data;
         %put NOTE_TEST_EVAL= 1.1 Check AE and PID data sets;
         %put NOTE_TEST_EVAL=--------------------------------;
         %put NOTE_TEST_EVAL= No AE or PID data set has been selected;
         %goto pgm_end;
      %end;
   *Here additional Program code can be included;
%pgm_end;
%mend test;
%test;

Pour un autre exemple de GOTO, vous pouvez vous reporte à la troisième partie de l’article intitulé « Mon paramètre de macro est-il rempli ? « .

h1

Sauvegarder une macro au delà d’une session SAS

janvier 8, 2009

Par défaut, une macro est créée le temps d’une session. En effet, elle est sauvegardée dans le catalogue réservé aux macros (macro catalog) de la bibliothèque WORK. Comment changer la bibliothèque en vue d’une utilisation ultérieure de la macro ?

1. Par défaut, créer une macro temporaire

Dans un premier temps, une macro appelée TMP_MACRO est créée. Cette macro est sauvegardée dans un fichier appelé un macro catalog de la bibliothèque WORK.

%macro tmp_macro;
proc print data=sashelp.class;
run;
%mend tmp_macro;

2. Sauvegarder de manière permanente la macro

A présent, il s’agit de sauvegarder la macro PERM_MACRO dans la biblioht`que SASREF. Comme précédemment, elle sera sauvegardée dans un catalogue ne pouvant contenir que des macro. Ce catalog s’appelle toujours SASMACR.

Grâce aux options SASMSTORED= et MSTORE, on précise à SAS que les macros à conserver (to store) seront à diriger dans la bibliothèque SASREF.

Ensuite, lors de la définition de la macro PERM_MACRO, on indique à SAS que cette macro fait partie des macros à conserver au delà de la session SAS. Elle sera donc sauvegardée dans la bibliothèque SASREF.

libname sasref 'C:/sasref';
options sasmstore=sasref mstored;

%macro perm_macro /store;
proc print data=sashelp.class;
run;
%mend perm_macro;

L’option STORE maintient la bibliothèque SASREF en activité. Il est alors impossible de désassigner la bibliothèque SASREF. Si vous avez une solution à ce problème, n’hésitez pas à nous la faire partager.

*libname sasref;
h1

23:59:59 et 23:59:60 avant minuit : pas pour SAS

janvier 5, 2009

Suite aux informations télévisées faisant l’annonce de l’ajoute d’une seconde intercalaire, je me suis intéressée sur l’usage que SAS fait de ces décisions. En effet, les journaux parlent de l’ajout d’une seconde en fin d’année 2008 pour continuer à être en adéquation avec le temps qui s’écoule avant que la terre n’effectue une rotation complète autour du soleil. Du coup, j’ai voulu savoir si SAS incluait ce changement dans sont format DATETIME.

1. A l’origine de l’histoire

Les secondes intercalaires (leap second en anglais) : les secondes intercalaires, tel est le nom données à ces secondes ajoutées de temps en temps en fin d’année.

Quelques sources d’information : Qu’il s’agisse du monde.fr ou du timesonline.co.uk, tous nous parlent de sa dernière incursion dans notre horloge du temps. Wikipedia nous parle rapidement de l’organisme international qui prend cette décision : le service international de la rotation de la terre et des systèmes de référence (IERS ou Internation Earth Rotation and Reference Systems Service www.iers.org)

23 secondes d’ajoutées avant d’atteindre le 1er janvier 2009 : Cette année on a compté 23:59:59, 2:59:60 et seulement après 00:00:00 et ce pour la 23ème fois. 1972 est la première année où est intervenu cette addition.

Des changements prévisibles peut de temps à l’avance : Le prochain ajout n’est pas encore confirmé avec certitude. On parle de 2012 ou 2013. Ceci explique alors en partie pourquoi  SAS n’inclut pas ces secondes dans son format DATETIME .

2. Tester avec un petit exemple sous SAS

Dans cet exemple, on crée deux variables DT1 et DT2.

data one;
  dt1='31DEC2008:23:59:59'dt;
  dt2='01JAN2009:00:00:00'dt;
run;

Après un simple PROC PRINT, on voit que SAS compte une différence d’une seconde et non de deux secondes entre les deux valeurs.

proc print data=one;
run;
      dt1           dt2

1546387199    1546387200

Si un format DATETIME. est appliqué sur ces donnés, SAS reste cohérent dans son choix et considère DT2 comme étant déjà en 2009.

proc print data=one;
  format dt1 dt2 datetime.;
run;
      dt1                 dt2

31DEC08:23:59:59    01JAN09:00:00:00
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

Combien de contrats ai-je au total ? (2/5) RETAIN

novembre 3, 2008

Après un premier article faisant appel à la procédure SQL pour identifier le nombre total de contrats d’un type donné à partir d’un data set SAS, voici comment un compteur dans une étape data peut résoudre le problème.

1. Renommer des variables

  • Avoir les mêmes noms en entrée et en sortie : Dans le cas présent, il faut définir de nouvelles variables ayant un nom différent de ceux existant. Pour avoir quand même au final le même nom qu’au départ, j’ai choisi de renommer mes variables d’origines rendant leur ancien nom de nouveau disponible.
  • Quel nom pour les variables ? Ces variables portent un nom commençant par un tiret bas (underscore). Cela permet d’avoir un nom toujours parlant et de les supprimer rapidement avec _: (supprimer toutes les variables commençant par un tiret bas).
data solution2 (drop=_: );
   set contrats (rename=(tel=_tel
                         habitat=_habitat);
   *...;
run;

D’autres variables sont supprimées :

  • La variable CLIENT disparaît dès de départ car il ne sert pas dans notre cas.
  • La variable NB_CNTR disparaît seulement à la fin car elle va servir pour faire nos calculs.
data solution2 (drop=_: nb_contr);
   set contrats (drop=client
                 rename=(tel=_tel
                         habitat=_habitat);
   *...;
run;

2. Créer un compteur

Une fois les variables d’origine renommées, les variables TEL et HABITAT sont initialisées à 0 avec un RETAIN. Cela veut dire que pour toutes les observations, ces variables ont dans un premier temps la valeur 0. SAS lit les observations les une après les autres. A chaque fois qu’une valeur de TEL est changée toutes celles qui suivent le sont aussi. C’est le principe du RETAIN.

data solution2 ;*(...);
   set contrats ;*(...);
   retain tel 0
          habitat 0;
   tel     = tel     + nb_cntr * _tel;
   habitat = habitat+  nb_cntr * _habitat;
run;

SAS initialise les variable TEL et HABITAT : Tout d’abord TEL=0 et HABITAT=0.

nb_cntrt _tel _habitat tel habitat
    5      1      0     0     0
    1      1      0     0     0
    2      0      1     0     0
    1      1      0     0     0
    3      0      1     0     0
    2      1      0     0     0

SAS lit la première ligne du data set : A la lecture de la première ligne du data set CONTRATS, la variable TEL est mise à jour. Sachant que pour la première observation, il a 5 contrats (NB_CNTRT=5 et _TEL=1), la première valeur de TEL est égale à 5 et toutes celles qui suivent aussi.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     5     0
    2      0      1     5     0
    1      1      0     5     0
    3      0      1     5     0
    2      1      0     5     0

SAS lit la seconde ligne du data set : A la lecture de la seconde observation, on ajoute 1*1 à 5. Le résultat (la valeur 6) se répercute sur toutes les observations de la variable TEL.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     6     0
    2      0      1     6     0
    1      1      0     6     0
    3      0      1     6     0
    2      1      0     6     0

SAS lit la troisième ligne du data set : A la lecture de la troisième observation, la valeur de TEL ne change pas car on ajoute zéro (0+2*0). Par contre, celle d’HABITAT change.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     6     0
    2      0      1     6     2
    1      1      0     6     2
    3      0      1     6     2
    2      1      0     6     2

A la fin : Au final, le data set a cette forme. Ce qui nous intéresse ici ce sont les valeurs 9 et 5 de la dernière ligne d’observations.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     6     0
    2      0      1     6     2
    1      1      0     7     2
    3      0      1     7     5
    2      1      0     9     5

3. Garder la dernière observation

A présent, il s’agit de ne garder que la dernière observation. On commence par créer une variable EOF par l’intermédiaire de l’option END= dans l’instruction SET. Le nom de la variable ici fait référence à l’expression End of File. Mais vous êtes libre de choisir le nom qui vous convient.

  • Une option sans parenthèses : On notera que END= est une option de l’instruction SET et non une option du data set CONTRATS. C’est la raison pour laquelle elle n’apparaît pas entre parenthèses.
  • Une option en fin d’instruction : Les options du data set listées entre parenthèses doivent suivre immédiatement le nom du data set. L’option END= ne peut être ajoutée qu’après.

Cette variable (EOT) a deux particularités :

  • Une variable temporaire : D’une part, elle ne sera pas conservée dans le data set final SOLUTION2 ;
  • Une variable binaire : D’autre part, la variable est binaire ; elle prend la valeur 1 pour la dernière observation, 0 autrement.
data solution2 (...);
   set contrats (...) end=eof;
   *retain ...;
   *tel=...;
   *habitat=...;
   if eof then output;
   *if eof=1 then output;
run;

La condition : Dans la condition qui suit, seule la dernière observation d’EOT a la valeur 1. C’est donc la seule qui est retenue dans la condition. Le « =1 » est implicite dans la condition. C’est pour cela que les deux instructions, celle active et celle en commentaire, sont identiques.

L’action basée sur la condition : Le mot OUTPUT redirige la ligne sélection avec la condition dans le data set final SOLUTION2.

A dans huit jours, pour retrouver une solution avec PROC MEANS.

Annexe : Rappel sur les données et l’étape data dans son ensemble :

data contrats;
   input client $ nb_cntr tel habitat;
   datalines;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
;
run;

data solution2 (drop=_: nb_cntr);
   set contrats (drop=client
                 rename=(tel=_tel
                         habitat=_habitat)
                 end=eof;
   retain tel 0
          habitat 0;
   tel     = tel     + nb_cntr * _tel;
   habitat = habitat + nb_cntr * _habitat;
   if eof then output;
run;