Archive for the ‘Par Niveau Certification’ Category

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

Les pièges d’Excel : Une colonne sans nom (GETNAME=YES)

Mai 24, 2009

Lors de l’importation d’un fichier Excel sous SAS au moyen de la procédure PROC IMPORT, la première ligne indique à SAS quel nom donné aux variables au lieu d’utiliser les lettres de l’alphabet. L’option par défaut est GETNAME=YES. Dans un cas, des informations peuvent être perdues. C’est ce que je vous propose de voir ici.

1. Le cas où tout va bien

Le tableau à importer contient 4 colonnes. La première ligne servira à SAS pour attribuer le nom des variables. La seconde ligne contient les données. Le tableau SAS aura 4 variables avec une observation chacune.

La procédure PROC IMPORT

proc import datafile=‘C:/sasref/getname_example1.xls’
out=getname_ex
dbms=xls
replace;
getname=yes;
run;

2. Un nom de colonne manquant

Dans le cas suivant, une des cellules de la première ligne est vide. SAS cherche un nom (GETNAMES=YES) mais n’en trouve pas. SAS n’importe pas la colonne concernée.. Le data set contient alors 3 variables avec une observation chacune.

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

Parler français : représenter un nombre 100 987,24

avril 18, 2009

Selon le pays les nombres sont présentés de manière différente. COMMA et COMMAX sont deux formats utilisés par SAS pour représentés les nombres mais ne s’applique pas au cas français. Vous verrez donc comment créer le format qui vous convient avec l’instruction PICTURE de PROC FORMAT.

1. La différence français/anglais

Les francophones présentent les nombres différemment des anglophones sur deux points.

  • Les milliers : Les chiffres des milliers sont séparés par un espace alors que les américains utilisent la virgule
  • Les décimales : Les décimales sont séparées par une virgule en français contre un point en anglais

2. La représentation par défaut de SAS

Par défaut, les nombres sous SAS sont simplifiés comme sur une calculatrice.

  • Les milliers : le seul séparateur est celui des décimales
  • Les décimales : le point fait office de séparateur pour les décimales

Pour une présentation à l’anglais, il faudra appliquer le format COMMA. Il n’existe à ma connaissance qu’une semi version française : le format COMMAX. En effet celui-ci utilise bien la virgule pour séparer les entiers des décimales mais il utilise aussi le point et non le blanc pour séparer les milliers. On préférera donc créer un format avec l’instruction PICTURE.

2. Un exemple

Créer un format : dans le cas présent, les nombres seont affichés jusqu’à 999999,99,  en ajoutant un espace entre les milliers et un virgule pour les décimales.

  • L’usage du 0 : il n’y aura pas de zéro affiché à l’avant du nombre si celui-ci est plus petit que 100000.
  • L’usage du 9 : Les décimales s’afficheront toujours avec deux chiffres après la virgules même si le second chiffre est un zéro.

proc format;
picture commafr other=’000 000,99′;
run;

Appliquer les formats COMMA,  COMMAX et format personnel

Dans cette étape data trois variables sont créées chacune avec une observation.

Dans les trois cas, un format avec une extension 9.2 est ajouté de manière permanente. On indique à SAS que le nombre ne dépassera normalement pas 9 caractères dont 2 pour les décimales.

data fr_en;
format
eg_english comma9.2
eg_semifrench commax9.2
eg_french commafr9.2;
eg_english=100987.24;
eg_semi_french=100987.24;
eg_french=100987.24;
run;

Voir le résultat

eg_english   eg_semifrench   eg_french

100,987.24     100.987,24    100 987,24

La variable EG_ENGLISH (exemple, anglais) reçoit, quant à elle, un format COMMA9.2 pour un affichage à l’américaine/l’anglais.

La variable EG_SEMIFRENCH (exemple,respectant partiellement la syntaxe française) reçoit u nformat COMMAX9.2.

La variable EG_FRENCH (exemple, français) reçoit le format créé manuellement COMMAFR9.2 pour un affichage avec un blanc entre chaque groupe de trois chiffres parmi dans la partie entière et deux chiffres pour la partie décimale.

Lectures complémentaires

SAS Online Doc

  • COMMAw.d Format
  • COMMAXw.d Format
  • PICTURE Statement
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

Ajouter une date dans un nom de fichier Excel, Word…

mars 12, 2009

Sous SAS, en créant un fichier .xls ou .rtf avec la syntaxe de l’ODS (Output Delivery System), il est parfois pratique d’ajouter dans le nom du fichier une date. Par exemple : listing_20090311.xls.

Nous verrons ici plusieurs représentations de la date et de l’heure : afin d’avoir des noms triables par ordre chronologique, l’année apparaît avant le mois et le jour.

La syntaxe proposée, %SYSFUNC(fonction, format), s’utilise dans d’autres cas que la définition d’un nom de fichier (.rtf, .xls, …). De manière générale, elle sert à utiliser des fonctions en dehors d’une étape data ou d’une procédure. Par exemple, elle peut être ajoutée dans une instruction TITLE.

1. L’objectif pour un programme exécuté le 11 mars 2009

L’objectif de l’exemple qui suit est d’obtenir un fichier .xls nommé class_20090311.xls dont la date change selon le jour de sa création.

La version fixe se présente ainsi : un fichier .xls est créé au moyen de ODS TAGSETS.EXCELXP. Il contient les données du data set SASHELP.CLASS. La création d’un fichier dans la fenêtre OUTPUT est suspendu le temps de la création du fichier .xls au moyen de l’instruction ODS LISTING CLOSE et ODS LISTING.

ods listing close;
ods tagsets.excelxp file='C:/sasref/class_20090311.xls';
proc print data=sashelp.class;
run;
ods tagsets.excelxp close;
ods listing;

2. Ajouter de la flexibilité avec %SYSFUNC

A présent, la date est définie automatiquement au moyen de la macro fonction %SYSFUNC. Cette fonction est dans ce cas particulier composée de deux paramètres :

  • la date SAS extraite au moins de la fonction TODAY()
  • le format à appliquer sur cette date

Résoudre le contenu de la fonction %SYSFUNC grâce aux guillemets doubles : la fonction %SYSFUNC fait partie du langage macro. Dès lors, pour obtenir la résolution de son contenu, il faut utiliser des guillemets doubles.

Retrouver la date d’exécution du programme grâce aux fonctions TODAY() ou DATE () : La fonction TODAY() retourne la date SAS d’exécution du programme. Une alternative est la fonction DATE(). Dans les deux cas, la fonction ne contient pas de paramètre.

Le format YYMMDDn. pour écrire 20090311 : Le format YYMMDDn. est un sous-ensemble de la fonction YYMMDD composée de 8 caractères, sauf indication contraire, faisant apparaître :

  • l’année en premier,
  • suivi du mois en chiffre et
  • enfin du jour.

Ce format avec l’extension « n » a la particularité de ne pas utiliser de symbole ou espace séparatant le jour, du mois et de l’année. Les 8 caractères par défaut de la fonction laisse de la place à une année exprimée par 4 chiffres.

ods listing close;
ods tagsets.excelxp file="C:/sasref/class_%sysfunc(today(),yymmddn.).xls";
proc print data=sashelp.class;
run;
ods tagsets.excelxp close;
ods listing;

3. Tester d’autres formes d’affichage

3.1 Ajouter des tirets bas entre le jour, le mois et l’année grâce à la fonction TRANSLATE

class_2009_03_11.xls : pour avoir des tirets bas (underscore) entre le jour, le mois et l’année, il n’existe pas de format directement applicable. Une solution est alors d’utilise un autre symbole et de le remplacer avec la fonction TRANSLATE.

Ici le format YYMMDD10 retourne une date de la forme 20009-03-11. Les traits d’union (hyphen) sont remplacés par des tirets bas (underscore).

ods tagsets.excelxp file=« C:/sasref/class_%sysfunc(translate(%sysfunc(today(),yymmdd10.),’_’,’-‘)).xls »;

3.2 Ajouter une heure avec TIME() et PICTURE (class_20090311_113057.xls)

Quelle fonction pour l’heure ? : La fonction TIME() retourne l’heure sous la forme d’un time SAS.

Quels formats pour l’heure ? : Le format HHMM. retournera les heures et les minutes, tandis que le format TIME. retournera en plus les secondes. Dans les deux cas cependant, les heures avant 10h apparaissent avec seulement un chiffre : 9:30 et non 09:30. Un espace remplace le zéro manquant.

L’instruction PICTURE de PROC FORMAT pour un format personalisé : Une solution est de créer un format personalisé au moyen de l’instruction PICTURE (PICTURE statement). Comme les lettres H, M et S n’inclus pas de zéro devant (leading zero) pour les nombres à un chiffres, il faut les ajouter dans l’instruction PICTURE.

Note : %0S fait référence aux secondes. Il n’est obligatoire que si vous voulez des secondes dans votre texte final.

proc format;
   picture sasref other=‘%0H%0M%0S’ (datatype=time);
run;

Ensuite, 

  • pour une heure à quatre chiffres (heure + minutes) , il faudra préciser le nombre 4 dans l’appel du format.
  • pour une heures à six chiffres (heures + minutes + secondes), c’est 6 qui doit être ajouté

ods tagsets.excelxp file=« C:/sasref/class_%sysfunc(today(),yymmddn.)_%sysfunc(time(),sasref6.).xls »;

Lectures complémentaires sur http://www.sasreference.fr

ODS

Les fonctions

Les formats :

Les macros fonctions

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

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

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 ? (5/5) PROC TABULATE

novembre 24, 2008

Ce dernier article de notre série sur le calcul d’un total par variable (contrat) sous SAS aborde la procédure PROC TABULATE. Comme précédemment, les résultats sont redirigés vers un data set.

1. Rappel

La source de la thématique : Cette série d’articles est basée sur une question posée sur le forum de http://www.commentcamarche.net : vous pouvez retrouver la question d’origine sur leur site.

Les autres articles : Vous pouvez retrouver les précédents articles de la série ici :

Les données :Les données sont sauvegardées dans un data set nommé CONTRATS. Il contient 4 variables :

  • l’identifiant de chaque client CLIENT,
  • le nombre de contrats NB_CNTR et
  • deux variables binaires TEL et HABITAT indiquant si oui ou non les fréquences s’appliquent.

Au total, on compte 9 contrats téléphoniques et 5 contrats d’habitation.

Créer le data set CONTRATS

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;

2. La réponse de PROC TABULATE

Lister les variables dans l’instruction VAR : Dans un premier temps les variables binaires TEL et HABITAT sont listées. Là encore il faut préciser le poids de chaque valeur. L’option WEIGHT introduit la variable NB_CONTR, notre coefficient multiplicateur.

Exprimer le calcul requis dans l’instruction TABLE : Pour chacune des variables TEL et HABITAT, la somme est faite en tenant compte du coefficient. Les résultats sont des nombres entiers mais SAS ajoute par défaut des chiffres après la virgule (des zéros donc ici). Pour s’en débarasser, un format 5. est appliqué aux sommes. La sonne ne devra donc pas être un nombre avec plus de 5 chiffres.

Empêcher l’affichage dans la fenêtre OUTPUT : La sortie générée par PROC TABULATE s’appelle TABLE. Par défaut, le résultat est envoyé dans la fenêtre OUTPUT. Pour empêcher cette redirection le temps du PROC TABULATE, les options ODS EXCLUDE doivent être activées.

Rediriger ses résultats dans un data set avec l’ODS (Output Delivery System) : Le data set contenant les résultats s’appelle SOLUTION5. Il est créé avec l’instruction ODS OUTPUT.

*ods exclude table;
proc tabulate data=contrats;*out=solution5;
   var tel habitat / weight=nb_cntr;
   table tel habitat, (sum='Frequency')*f=5.;
   ods output table=solution5;
run;
*ods exclude none;

L’ancienne méthode pour créer un data set, l’option OUT= : L’ancienne méthodeconsiste à ajouter l’option OUT= dans l’instruction PROC TABULATE. Mais cette syntaxe n’est pas généralisable à toutes les procédures et est donc plus difficile à se souvenir pour des utilisations occasionnelles.

3. Améliorer le fichier de sortie

Un simple PROC PRINT sur le fichier SOLUTION5 montre que

_TYPE_ _PAGE_ _TABLE_ tel_Sum habitat_Sum

   0      1      1        9       5

Pour changer l’orientation des résultats, vous pouvez faire appel à un PROC TRANSPOSE.

proc transpose data=solution5 out=solution5 (drop=_LABEL_);
   var tel_sum habitat_sum;
run;

Reste à vous d’améliorer la présentation avec des RENAME, LABEL appropriés, etc.

  _NAME_     COL1
tel_Sum       9
habitat_Sum   5
h1

Lire des données d’un fichier .TXT sans perdre d’information (les options d’INFILE)

novembre 7, 2008

L’accès à des données contenues dans un fichier externe du type .TXT se fait sous SAS par l’intermédiaire d’une étape data et de l’instruction INFILE. Plusieurs options sont possibles pour cette instruction. Il est important de connaître les forces et faiblesses de chacune afin de faire le bon choix. Cet article vous présentera dans un premier temps le fichier .TXT qui servira d’exemple. En premier lieu, il sera appelé avec l’option FLOWOVER, l’option par défaut. Puis, cela sera le tour des options TRUNCOVER et MISSOVER/PAD.

1. Aperçu sur les données contenu dans le fichier .TXT

Afin de montrer les nuances entre les options FLOWOVER, TRUNCOVER et MISSOVER, un fichier EG_INFILE.TXT est créé. Ce fichier contient les données pour deux variables caractères CNTRY (country) et CNT (count).

Dans l’aperçu qui suit, j’ai remplacé les espaces par des points afin de vous puissiez visualiser la différence que peuvent créer certains espaces.

  • La première ligne contient 2 caractères
  • Les seconde et troisième lignes contiennent 12 caractères
  • L’avant dernière ligne n’en contient que 4
  • La dernière en contient 12 si on inclus les espaces de fin.

Note : « e.g. » est la version raccourcie de « example » en anglais. C’est donc notre équivalent de « ex ».

IT
CA.12.......
BE.123456789
KR.
MY.2
FI.1........

Le choix du FILENAME : Par choix, je crée un mot SASREF qui désigne le chemin d’accès au fichier EG_INFILE.TXT. Cela évitera d’avoir à recopier le chemin dans chaque étape data. Toute mise à jour ou correction du chemin d’accès se fera en une seule fois évitant tout oubli.

filename sasref 'C:/sasref/eg_infile.txt';

Note : Il est important de définir une longueur pour les variables caractères. Sinon les variables ayant plus de 8 caractères sont tronquées. Dans notre cas, la valeur 123456789 deviendrait 12345678.

2. FLOWOVER, l’option par défaut

Par défaut, SAS applique l’option FLOWOVER avec une instruction INFILE. Ainsi l’instruction INFILE mise en commentaire, en ajoutant une étoile en tête d’instruction, donnerait le même résultat que celle active.

data eg_flowover;
   infile sasref;
   *infile sasref flowover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

L’aperçu qui suit montre très clairement que SAS continu sa lecture sur la ligne suivante s’il n’a pas trouvé une valeur pour chaque variable dans la ligne actuelle.

  • Créer la première ligne d’observations : En ligne 1, il manque une valeur pour CNT. SAS va en ligne deux et récupère la première valeur. Il ignorera toutes les valeurs qui peuvent exister sur le reste de la ligne. Il lui a donc fallu deux lignes en entrée pour créer une ligne en sortie.
  • Créer la seconde ligne d’observations : après avoir lu les deux premières lignes, SAS passe à la troisième ligne pour créer la seconde ligne d’observations. Il trouve son bonheur ici puisqu’il y a une valeur par variable.
  • Créer la troisième ligne d’observations : à la ligne suivante, il manque de nouveau une valeur. SAS assigne la valeur KR à la variable CNTRY. Mais ne trouvant pas de valeur pour la variable CNT, il passe à la ligne suivante et trouve la valeur MY.
  • Créer la quatrième et dernière ligne d’observations : il ne reste a SAS plus qu’une ligne de disponible dans le fichier d’entrée. Cette ligne contient une observation par variable. SAS est content avec.
cntry  cnt

  IT   CA
  BE   123456789
  KR   MY
  FI   1

3. L’option TRUNCOVER empêche le passage à la ligne et ne se formalise pas des longueurs

L’option TRUNCOVER palie à ce problème en empêchant à SAS d’aller voir à la ligne suivante

data eg_truncover;
   infile sasref truncover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

Le résultat est comme escompté : 

cntry   cnt
  IT
  CA    12
  BE    123456789
  KR
  MY    2
  FI    1

4. L’option MISSOVER empêche le passage à la ligne

Les limites de l’option MISSOVER avec un INFILE : L’option MISSOVER est une autre option possible de l’instruction INFILE. Elle présente néanmoins une limite due à des espaces.

data eg_missover;
   infile sasref missover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

Dans l’exemple, la valeur de CNT (2) quand CNTRY=MY disparaît, alors quela valeur de CNT (1) quand CNTRY=FI reste. Alors que la Qu’est ce qui a provoqué cela ?

Vous souvenez vous de la remarque concernant les espaces en fin de ligne dans la première section de cette article. SAS recherche 9 caractères pour créer une valeur pour CNT. Hors quand CNTRY=MY, il n’en trouve qu’un. Cela ne le satisfait pas. Comme, avec MISSOVER, il ne peut pas aller voir sur la ligne d’après. Il se contente de mettre une valeur manquante.

cntry   cnt

  IT   
  CA    12
  BE    123
  KR   
  MY   
  FI    1

L’équivalent de TRUNCOVER : L’option MISSOVER en combinaison avec l’option PAD fournira le même résulat que l’option TRUNCOVER. Autant donc utiliser un seul mot en la personne de TRUNCOVER.

data eg_missover_pad;
   infile sasref missover pad;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

Le cas particulier du DATALINES : MISSOVER avec un DATALINES ne rencontre pas le problème des blancs de fin de ligne manquants.

data eg_missover;
   infile datalines missover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
   datalines;
IT
CA 12
BE 123456789
KR
MY 2
FI 1
;
run;

Conclusion

Nous avons vu un cas particulier de l’instruction INFILE : lecture d’un fichier dans lequel chaque ligne est sensée représenter une ligne d’observations.

Par défaut, SAS recherche autant d’emplacements (texte ou espaces) dans le fichier qu’il lit que celui donné par la longueur d’une variable. Faute de quoi SAS jetera un coup d’oeil à la ligne suivante (FLOWOVER) ou ignorera certaines valeurs (MISSOVER) selon l’option indiquée dans l’instruction INFILE.

L’option TRUNCOVER répond aux deux problèmes (passage à la ligne et manque de place sur une ligne). Il est donc judicieux de privilégier l’option TRUNCOVER sur MISSOVER pour ce problème précis.