Archive for the ‘Base’ Category

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

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

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

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.

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

Mettre à jour un data set à partir d’un autre

octobre 30, 2008

Si vous avez déjà utilisé un peu SAS, vous connaissez probablement les instructions SET et MERGE. Aujourd’hui, voici un article sur l’instruction UPDATE pour mettre à jour un data set. Cette instruction de l’étape DATA doit être utilisée en gardant en tête deux notions importantes expliquées ici.

Pour réviser ou découvrir les instructions SET et MERGE, reportez-vous aux articles suivants :

1. Un data set de base et un autre contenant des informations nouvelles

Dans notre exemple nous avons deux data sets YEAR_2007_FRST et YEAR_2007_EXTRA.

Le premier data set YEAR_2007_FRST est le data set à mettre à jour : il contient

  • 4 observations et
  • 3 variables numériques : MONTH (month pour mois), CRIT (criteria pour critère), VAL (value pour valeur).
data year_2007_frst;
   input month crit val;
   datalines;
1 2 3
4 5 6
9 9 9
10 10 10
;
run;

Le second data set YEAR_2007_EXTRA contient des informations à ajouter au premier data set. Il est composé de :

  • 5 observations : certaines lignes d’observations du premier data set sont présentes mais pas toutes. Il y a aussi des lignes d’observations en plus. Parfois la valeur de la variable MONTH est identique mais par forcément celle des autres variables.
  • 4 variables numériques : il y a les variables déjà présentes auparavant et une nouvelle variable.
data year_2007_extra;
   input month crit val val2;
   datalines;
1 2 3 4
1 4 5 6
7 8 9 10
9 9 . 9
10 10 .A 10
;
run;

2. Choisir une ou plusieurs variable clés

Avec l’instruction UPDATE, il faut définir une liste de variables clés. Lorsque la combinaison est présente dans les deux fichiers, les autres variables sont mises à jour. Sinon, une nouvelle ligne d’observations est ajoutée.

Ici, je choisis de désigner une ligne avec la variable MONTH et seulement la variable MONTH. Lorsque la variable MONTH du premier et du second data sets coïncident, les autres observations sont mises à jour en se servant du deuxième fichier (YEAR_2007_EXTRA).

data year_2007_frst;
   update year_2007_frst
          year_2007_extra;
   by month;
run;

Ajouter de nouvelles observations : Avec l’exemple de l’article, la ligne où MONTH = 7 n’est pas présente dans le premier data set. Elle est ajoutée.

Ajouter de nouvelles variables : La variable VAL2 est également nouvelle et ajoutée.

3. Une seule ligne d’observation par clé dans le fichier additionnel

Lorsque le fichier additionnel (WEAR_2007_EXTRA) contient plusieurs observations, seule une est gardée. Il est donc préférable d’avoir un fichier avec une seule ligne d’observation par variable clé.

Dans notre exemple, le fichier servant pour la mise à jour a deux lignes d’observations avec MONTH égales à 1. SAS utilisera, dans un premier temps, la première pour mettre à jour le fichier. Puis réécrira dessus avec la seconde ligne d’observation.

  • Avant :MONTH=1, CRIT=2, VAL=3
  • Après : MONTH=1, CRIT=4, VAL=5 et VAL2=6.

4. Ignorer les valeurs manquantes du fichier de mise à jour

Si dans votre fichier de mise à jour il y a des valeurs manquantes alors que dans le fichier d’origine ce n’était pas le cas, SAS n’effacera pas la valeur sauf si la nouvelle valeur est une valeur manquante particulière (special missing).

Dans notre exemple,

  • quand MONTH=9, VAL=9 avant et après, même si dans le data set additionnel, VAL était manquant (symbole point).
  • quand MONTH=10, VAL=10 avant et VAL=.A après, car la nouvelle valeur est une valeur qualifiée par SAS de valeur manquante spéciale.

Au final le nouveau fichier YEAR_2007_FRST, auquel un autre nom aurait pu être donné, se présente ainsi :

month crit val val2
  1     4   5    6
  4     5   6    .
  7     8   9   10
  9     9   9    9
  10   10  .A   10

5. Avoir une seule ligne par BY variable dans le fichier à mettre à jour

Après avoir noté que SAS ne remplace pas les valeurs existantes par des valeurs manquantes, je tenais à souligner une seconde particularité du UPDATE. SAS estime que la variable clé devrait identifier de manière unique une ligne d’observations dans le fichier à mettre à jour.

Dans notre exemple, SAS que la variable clé est MONTH. Il estime que chaque valeur de MONTH se doit d’être unique dans le fichier à actualiser (YEAR_2007_FRST).

Je vais donc ajouter une ligne pour que MONTH=1 apparaisse deux fois et voir la gestion qu’en fait SAS.

data year_2007_frst;
   input month crit val;
   datalines;
1 2 3
1 9 9
4 5 6
9 9 9
10 10 10
;
run;

Si ce n’est pas le cas deux choses se passe :

  • D’une part, un WARNING apparaît dans la log.
  • D’autre part, parmi les lignes ayant les mêmes valeurs clés, seule la première ligne sera actualisée.

Ici, la log contiendra le WARNING suivant :

  • WARNING: The MASTER data set contains more than one observation for a  BY group.

Et notre fichier final, lorsque la variable MONTH =1, seule aura

month crit val val2
  1     4   5    6
  1     9   9    .
  4     5   6    .
  7     8   9   10
  9     9   9    9
  10   10  .A   10

En résumé, avec une instruction UPDATE, il est important de garder à l’esprit trois notions :

  • les valeurs manquantes simples n’effacent pas les données d’origine.
  • le data set avec les données actualisées contiendra une seule ligne d’observation par variable clé et des conséquences si ce n’est pas le cas.
  • le data set à actualiser doit contenir une seule ligne d’observation par variable clé et ainsi respecter la définition de la syntaxe.

Vous trouverez dans la documentation en ligne une page sur UPDATE Statement pour compléter votre lecture.

h1

Afficher 7h30 du matin sous la forme 07:30

octobre 24, 2008

Les heures, minutes et secondes sont enregistrables sous SAS sous la forme d’un seul chiffre exprimant cette durée en seconde. On parle d’heure SAS (SAS time). A l’affichage, il y a le format TIME5. pour représenter les heures et les minutes uniquement à partir de 5 caractères au maximum. Mais ce format omet le zéro de début pour les heures à un chiffre comme 9h00. Voici donc dans cet article plusieurs solutions pour contourner le problème allant d’un format avec PICTURE, en passant par les fonctions RIGHT et TRANWORD.

1. Le data set servant d’exemple

Pour présenter les variantes, un data set NEWTIME est créé. Il contient une variable SEC avec 4 valeurs exprimant le temps en secondes et une valeur manquante.

  • 7h30 : prenons 7h30m00s ou 27000 secondes (7x60x60*60) pour exprimer 7h30 du matin
  • 15h : prenons maintenant 15h00m00s ou 54000 secondes pour obtenir 15h
  • 14h59 : pour désigner 14h59, des valeurs entre 14h59m00s (53940 sec) et 14h59m59s (53999 sec) sont possibles. Dans l’exemple, ces deux extrêmités sont choisies.
data newtime;
   input sec;
   datalines;
27000
54000
53940
53999
.
;
run;

2. Un format créé avec l’instruction PICTURE

La solution la plus flexible est probablement de créer un nouveau format. De cette manière, la valeur d’origine en seconde est encore disponible. Ce format peut aussi servir à convertir une variable caractère en heure SAS.

L’instruction PICTURE : Le format SASREF est construit à partir de l’instruction PICTURE dans une procédure PROC FORMAT. Le symbole %H réfère à des heures allant de 0h à 23h. Le symbole %M désigne des minutes allant de 0min à 59min. Le zéro intercalé ajoutera un zéro pour les valeurs inférieures à 10.

Documentation : Vous pouvez consulter la documentation en ligne pour connaître tous les symbole comme %M, %H disponible avec l’instruction PICTURE : PICTURE Statement.

proc format;
   picture sasref other='%0H:%0M' (datatype=time);
run;

Dans cet exemple, une variable caractère TIME_C est créée à partir de la fonction PUT et du format SASREF affichant 5 caractères.

Vous pouvez aussi exécuter l’instruction FORMAT pour appliquer le format SASREF5. à la variable SEC.

data newtime;
   set newtime;
   time_c=put(sec,sasref5.);
   *format sec sasref5.;
run;

3. Ajouter une condition pour traiter les valeurs manquantes

Une seconde variable TIME_C2 applique une contrainte particulière pour les valeurs manquantes. En effet, le format SASREF renvoie le mot ERROR si la valeur d’origine est manquante.

data newtime;
   set newtime;
   if not missing (sec) then time_c2=put(t1,sasref5.);
run;

4. Passer d’une valeur texte 7:30 à une valeur 07:30 avec les fonctions RIGHT et TRANWRD

Une troisième variable TIME_C3 est construite en deux étapes. Voyons donc l’interprétation faite pour une heure comme 7:30.

  • Fonction PUT et format TIME5 pour créer une valeur 7:30 : Tout d’abord, la fonction PUT combinée au format TIME5. crée une variable caractère de la forme 7:30 avec une longueur de 5. Par défaut, le texte est aligné à gauche. Le blanc est donc situé en 5ème position.
  • Fonctions RIGHT et TRANWORD pour ajouter un blanc en tête : Ensuite, une variable caractère 7:30 est convertie en 07:30, etc. Dans un premier temps, la fonction RIGHT aligne le texte à droite. Le blanc est en première position. Dans un second temps, la fonction TRANWRD remplace le blanc par un zéro.
data newtime;
   set newtime;
   if not missing (sec) 
   then time_c3=tranwrd(right(put(sec,time5.),' ','0');
run;

LA documentation en ligne propose une page sur les fonctions TRANWORD et RIGHT.

  • TRANWORD Function
  • RIGHT Function

Vous pouvez aussi consultez l’article sur la fonction PUT :

5. Aperçu des données

Voici un aperçu des différentes variables après :

sec     time_c time_c2 time_c3

27000   07:30   07:30   07:30
53940   14:59   14:59   14:59
53999   14:59   14:59   14:59
54000   15:00   15:00   15:00
    .   ERROR
h1

Ajouter des indentations dans un tableau

octobre 20, 2008

Avec PROC REPORT et PROC TABULATE, SAS crée des tableaux à partir d’un jeu de donnée (SAS data set). Dans certains cas, la lisibilité de ces tableaux est améliorée en ajoutant des indentations au texte (to indent). Nous verrons donc ici deux approches possibles : l’option INDENT de PROC TABULATE et le caractère hexadécimal pour les blancs dans PROC REPORT.

1. Un exemple pour illustrer la syntaxe sur les indentations

Dans les essais cliniques, trois types de tableaux/listings sont produits :

  • Démographie (demography) : descriptif des patients en terme d’âge, de sexe, de pays, etc.
  • Efficacité (efficacy) : l’efficacité du médicament par rapport à un autre ou par rapport à un effet placebo (le patient prend en médicament en pensant qu’il est actif alors qu’il ne l’est pas).
  • Sécurité (safety) : ces tableaux permettent l’analyse des effets secondaires d’un médicament.

Je vais prendre la cas d’un tableau démographique version réduite (trois colonnes) pour présenter la syntaxe sur les indentations.

  • La première colonne contient les caractéristiques démographiques (sexe et pays),
  • la seconde colonne compte le nombre de patients (N) pour chaque caractéristique
  • la troisième colonne donnera la répartition des patients en pourcentage (%).
---------------------------------
|                   |  N  |  %  |
|-------------------------------|
|Gender             |           |
|   Male            |   12| 48 %|
|   Female          |   13| 52 %|
|Country            |           |
|   France          |    6| 24 %|
|   Belgium         |   10| 40 %|
|   Luxemburg       |    9| 36 %|
---------------------------------

Des variables numériques pour ordonner les valeurs : Pour faciliter le tri des données, j’ai choisi d’avoir des variables numériques dans mon data set SAS sur lesquelles j’applique des formats.

  • Ainsi la premier variable (GRP) réfère à l’intitulé des caractéristiques démographiques : Gender (1) Country (2).
  • La seconde variable (SUBGRP) est l’ordre pour chaque caractéristique. J’aurais pu choisir des valeurs de 1 à 5 mais j’ai préféré que chaque chiffre des décimal corresponde à la variable GRP.
data patient_info;
   input grp subgrp cnt_n pct_n;
   datalines;
1 11 12 0.48
1 12 13 0.52
2 21  6 0.24
2 22 10 0.40
2 23  9 0.36
;
run;

Je choisi de créer des formats du même nom (GRP et SUBGRP) :

proc format;
   value grp     1='Gender'
                 2='Country';
   value subgrp 11='Male'
                12='Female'
                21='France'
                22='Belgium'
                23='Luxemburg';
run;

En outre, je crée un format avec PICTURE pour l’affichage des pourcentages. La raison est la suivante : par défaut, deux chiffres après la virgules apparaissent avec PROC TABULATE. De plus, je souhaite voir le symbole % s’afficher pour chaque pourcentage.

Un format BEST5. est ajouté pour des fréquences composées jusqu’à 5 chiffres sans décimale. De plus, il remplace les points par des blancs. Cela servira pour PROC REPORT.

proc format;
   picture pct (round) .     = ''
                       other = '099 %' (multiplier=100);
   value cnt           .     = ' '
                       other = [best5.];
run;

Dans les deux exemples qui suivent une indentation est formée de trois blancs.

2. L’option INDENT de PROC TABULATE

Dans l’exemple suivant, les deux variables GRP et SUBGRP sont traitées comme des variables textuelles.

L’instruction TABLE contient l’option INDENT= et précise ainsi le nombre de blancs pour décaler les valeurs de la variable SUBGRP vers la droite. Le résultat a été donné en début d’article.

proc tabulate data=patient_info noseps;
   class grp subgrp;
   table grp=''*subgrp='', cnt_n='N'*sum=' '*f=5.
                           pct_n='%'*sum=' '*f=pct.
         / rts=20 indent=3;
   format grp grp. subgrp subgrp.;
run;

Les options NO=SEPS et RTS= sont là pour personnaliser la mise en forme. Pour plus de précisions sur ces options, vous pouvez consulter la documentation en ligne :

  • NOSEPS sur la page « PROC TABULATE Statement »
  • RTS= sur la page « TABLE Statement »

3. Créer des variables alphanumériques (caractères) avec PROC REPORT

Ajouter une ligne pour chacune des caractéristiques : Toutes les informations sont créées manuellement. Ainsi, il y a en plus une ligne pour chaque groupe dans le data set SAS. Au lieu d’avoir 5 lignes, on en aura 7. Pour chaque nouveau GRP, la variable SUBGRP prendre la valeur du GRP + un zero afin d’apparaître en premier dans le rapport après un tri.

proc sort data = patient_info 
          out  = patient_report;
   by grp subgrp;
run;
data patient_report;
   set patient_report;
   by grp subgrp;
   output;
   if first.grp then
      do;
         subgrp=grp*10;
         cnt_n=.;
         pct_n=.;
      end;
run;

Trier par SUBGRP pour afficher les données dans l’ordre voulu.

proc sort data=patient_report;
   by grp subgrp;
run;

Une fois triées les données sont toujours numériques.

grp subgrp cnt_n pct_n

  1    10     .     .
  1    11    12  0.48
  1    12    13  0.52
  2    20     .     .
  2    21     6  0.24
  2    22    10  0.40
  2    23     9  0.36

Créer des variables caractères : la variable DSPLAY nouvellement créée peut contenir jusqu’à 15 caractères. Elle est composée des variables GRP et SUBGRP converties avec la fonction PUT.

Des hexadécimales pour créer des blancs : Les espaces sont créés à partir de valeurs hexadécimales. On répète ici trois fois A0 entre guillemets pour créer trois espaces. La lettre x qui suit précise à SAS qu’il s’agit d’hexadécimales. Ces trois blancs sont concaténés au résultat de la fonction PUT grâce aux deux barres.

data patient_report;
   length dsplay $15;
   set patient_report;
   if subgrp=0 then dsplay=put(grp,grp.);
   else dsplay='A0A0A0'x || put (subgrp,subgrp.);
   cnt_c=put(cnt_n,cnt.);
   pct_c=put(pct_n,pct.);
run;

Trier les données : La variable SUBGRP sert uniquement à définir l’ordre d’affichage des données mais n’apparaît pas dans le tableau final (option NOPRINT dans l’instruction DEFINE).

Enlever le titre de la colonne : La variable DSPLAY contient les caractéristiques démographiques. Aucun nom n’apparaîtra dans le titre de la colonne. Si les guillemets vides ne sont pas précisés, le nom de la variable est affiché.

Aligner à droite : Les variables caractères CNT_C et PCT_C sont affichées en tant que texte (DISPLAY) et leurs observations sont alignées à droite plutôt que d’être centrées (option RIGHT).

proc report data=patient_report;
   columns subgrp dsplay cnt_c pct_c;
   define subgrp / noprint order order=data;
   define dsplay / ' ' display;
   define cnt_c  / 'N' display right;
   define pct_c  / '%' display right;
run;

Dans ce cas, la sortie se présente sans ligne autour du cadre :

                     N      %
Gender
   Male             12   48 %
   Female           13   52 %
Country
   France            6   24 %
   Belgium          10   40 %
   Luxemburg         9   36 %

Sur le blog, vous trouverez d’autres articles sur les notions abordées ici :

h1

Copier la structure d’un data set et se séparer des données

octobre 16, 2008

Sous SAS, comment récupérer les caractéristiques d’un data set dans un autre data set sans les données et ainsi s’épargner un travail occasionnel mais qui peut vite devenir fastidieux ? Le nom des variables, leur position dans le data set et leurs autres attributs (type, longueur, format, informat) forme la structure d’un data set. Pour les récupérer, deux notations sont offertes : l’option OBS= dans une étape data et le mot LIKE dans une procédure SQL.

1. Créer le data set servant d’exemple

Pour illustrer les deux notations, nous partirons d’un data set nommé CLASS contenant une ligne d’observations et trois variables :

  • le nom de l’élève (NAME),
  • la date de début du cursus (SDT pour starting date) et
  • la date de fin du cursus (EDT pour ending date).

data class;
attrib name length=$15 label=‘Nom’
sdt informat=date9. format=date9. label=‘Starting Date’
edt informat=date9. format=date9. label=‘Ending Date’;
input name $ sdt edt;
datalines;
Charline 06OCT2006 15JUN2007
;
run;

Un PROC CONTENTS résumera les attributs des variables de la manière suivante :

proc contents data=class;
run;

# Variable Type Len Pos Format Informat Label

3 edt Num 8 8 DATE9. DATE9. Ending Date
1 name Char 15 16 Nom
2 sdt Num 8 0 DATE9. DATE9. Starting Date

1. Créer un data set vide

Dans cette première partie, un data set SQL_SOLUTION et ETAPE_DATA sont créés. Les deux ont la même structure

La procédure SQL : Au lieu de désigner toutes les variables à garder après un AS SELECT, on passe directement au data set de référence en l’introduisant avec le mot LIKE.

proc sql;
create table sql_solution like class;
quit;

L’étape data : L’option data set OBS= sur le fichier d’entrée précise qu’aucune observation ne sera lue. Seul le ‘header’ du data set contenant les caractéristiques sont lues par SAS et sauvegardées dans le data set de sortie ETAPE_DATA.

data etape_data;
set class (obs=0);
run;

SAS ira un peu plus vite avec une instruction STOP.

data etape_data;
set class;
stop;
run;

3. Ajouter des observations au data set vide

Une fois le data set copié sans les observations deux lignes sont ajoutées. La première désigne Jean-Pierre qui a début en janvier 2006. Christophe est nommé en second. Il a début le 7 octobre 2005 et terminé le 18 juin 2007.

La procédure SQL : Dans la PROC SQL, je vous propose d’ajouter les observations manuellement grâce à l’instruction INSERT INTO.

proc sql;
create table sql_solution like class;
insert into sql_solution
set name=‘Jean-Pierre’, sdt=’10JAN2006′d
set name=‘Christophe’, sdt=’07OCT2005′d, edt=’18JUN2007′d;
quit;

L’étape data : Dans un data step, les nouvelles observations sont sauvegardées dans un autre data set et sont ajoutées au moyen de l’instruction SET.

data add;
name=‘Jean-Pierre’;
sdt=’10JAN2006′d;
output;
name=‘Christophe’;
sdt=’07OCT2005′d;
edt=’18JUN2007′d;
output;
run;

data etape_data;
set class (obs=0)
add;
run;

Note : Dans ce cas, il faut que le data set contenant la structure apparaissent en premier. SAS sauvegarde toujours la première variable qu’il rencontre avec ses attributs. Proposer une autre variable du même nom avec des attributs différents ensuite n’alternera pas celles sauvegardées en premier.

h1

Renommer une variable (RENAME)

octobre 14, 2008

Pour renommer une variable SAS dispose d’une option RENAME applicable dans une étape data et dans une procédure. De plus, l’instruction RENAME de l’étape data et le mot-clé AS de la PROC SQL sont disponibles. Voici donc une présentation de ces différentes notations.

La base des exemples :

Pour illustrer le propos, le data set CLASS de la bibliothèque SASHELP aura deux variables à renommer : la variable NAME deviendra la variable NOM et la variable HEIGHT s’appellera TAILLE.

Une observation seulement sera gardée : celle concernant ‘Barbara’. Selon que les variables sont renommées dans le fichier d’entrée ou le fichier de sortie, la variable NAME ou NOM sera utilisée pour définir la condition.

Quel ordre ? : Qu’il s’agisse d’une option ou d’une instruction RENAME, il faut utiliser le signe égal (=) avec :

  • en premier, à gauche le nom actuel de la variable
  • en dernier, à droite le nouveau nom.

Pour s’en souvenir, vous pouvez imaginer une forme de flèche. A=>B symbole alors variable A donne/devient variable B).

1. Les options du data step en solitaire

Après avoir donné le nom d’un data set dans une étape data ou dans une procédure comme PROC SORT ou PROC TRANSPOSE, il est possible de lister des options entre parenthèses parmi lesquelles on trouve RENAME. L’option s’applique donc au data set nommé juste avant.

Dans une étape data, il est possible d’appliquer l’option RENAME sur les data sets à lire ou sur les data sets créés. Voici deux exemples avec des instructions SET. Cela marche aussi avec d’autres instructions nommant un data set comme MERGE.

Dans ce premier exemple, les variables NAME et HEIGHT du data set d’entrée (SASHELP.CLASS) sont renommées. Une fois cela fait, SAS effectue les étapes suivantes à savoir garder les observations se référant à Barbara. C’est pour cela que la condition s’applique sur la variable NOM.

data opt_in;
set sashelp.class (rename=(name=nom height=taille));
if nom=‘Barbara’ then output;
run;

Dans ce second exemple, l’option RENAME est appliquée sur le fichier de sortie. La condition est donc traitée par SAS avant que les variables soient renommées. Il faut désigner la variable avec son nom d’origine (NAME) dans la condition.

data opt_out (rename=(name=nom height=taille));
set sashelp.class;
if name=‘Barbara’ then output;
run;

Les deux data sets OPT_IN et OPT_OUT donnent le même fichier final.

nom Sex Age taille Weight

Barbara F 13 65.3 98

2. Les procédures

De la même manière, l’option RENAME peut s’appliquer sur le fichier d’entrée (sauf PROC SQL) et de sortie d’une procédure. Voici deux exemples avec les procédures PROC SORT et PROC SQL.

proc sort data=sashelp.class
out=class (rename=(name=nom height=taille));
by age;
run;

proc sql;
create table opt_out (rename=(name=nom height=taille)) as
select *
from sashelp.class;
quit;

La procédure SQL dispose du mot-clé AS pour renommer une variable en particulier parmi celles énumérées.

proc sql;
create table sql_as as
select name as nom, sex, age, height as taille, weight
from sashelp.class;
quit;

3. L’instruction RENAME du data step

Il existe une instruction RENAME s’appliquant uniquement à l’étape data. Il est important dans ce cas particulier de se rappeler que les variables sont renommées seulement une fois le data set final (INSTRUCT) créé. Le processus de SAS est donc le même qu’avec l’option sur le fichier OPT_OUT.

data instruct;
set sashelp.class;
rename name=nom height=taille;
if name=‘Barbara’ then output;
run;

4. L’option RENAME combinée avec d’autres options du data step

L’option RENAME n’est qu’une des options du data set SAS. Parmi les autres options les plus courantes, citons KEEP, DROP, WHERE, FIRSTOBS et OBS.

Dans ce dernier exemple, on pourra remarquer que l’option WHERE utilise la variable sur l’âge une fois celle-ci renommée. Tandis que l’option KEEP désigne la variable âge d’origine.

data class;
set sashelp.class (keep=age where=(_age=12) rename=(age=_age));
run;

h1

Mon petit doigt me dit que… le mot commence en position 2 (Fonction INDEX)

octobre 10, 2008

Pour savoir si un mot est présent dans une chaîne de caractère, il y a la fonction INDEX. Celle-ci retourne la position d’un « mot » dans une chaîne de caractère. Parmi les fonctions qui lisent les observations textuelles sous SAS, la fonction INDEX fait probablement partie du top 10 des fonctions les plus usuelles.

1. Deux paramètres de base

La chaîne de caractères à analyser est le premier paramètre de la fonction INDEX. Comme toute fonction, elle définie au choix par :

  • le texte entre guillemets
  • la variable caractère contenant toutes les observations à traiter.

Le texte à trouver est le second paramètre de la fonction INDEX. On le donne généralement entre  guillemets.

2. Que retourne la fonction ?

La fonction retourne un nombre : le nombre généré par la fonction INDEX représente la position de la première lettre du mot recherché. Si plusieurs mots sont disponibles dans la chaînes, SAS s’arrête au premier.

Et si aucun mot n’est présent ? Dans le cas où le mot n’est trouvé, la fonction INDEX retourne la valeur zéro. Ainsi si INDEX retourne une valeur supérieure à zéro, le mot est présent dans la chaîne de caractère, sinon il est absent.

3. Minuscules ou majuscules

La lettre A (majuscule) et a (minuscule) ne sont pas identiques. La fonction est sensible à la case.

Si la case de la chaîne de caractère vous importe peu, considérez la chaîne de caractères mise en majuscule (par exemple) avec la fonction UPCASE.

4. Un exemple

Dans l’exemple ci-dessous, le data set ONE a une ligne d’observation et trois variables X, Y et Z.

La variable Y retourne la position du mot ‘de’ (minuscule) dans la chaîne de caractères ‘ABC def DEG’. Il s’agit donc de la position 5.

La variable Z retourne la position du mot ‘DE’ (majuscule) dans la chaîne de caractères ‘ABC def DEG’. Il s’agit donc de la position 9.

data one;
x=‘ABC def DEG’;
y=index(x,’de’);
z=index(x,’DE’);
run;