Archive for the ‘Les Fontions’ Category

h1

Les fonctions put et input – un sujet épineux

novembre 23, 2022

Découvrir le cours sur Udemy

Pour convertir une valeur du caractère au numérique et inversement, ou encore du caractère au caractère / du numérique au numérique, il est courant de passer par les fonctions put et input. Grâce à ces fonctions historiques et aux nouvelles fonctions putn, putc, inputn et inputc, il est possible de changer le type d’une variable, sélectionner des observations en fonction de valeurs formatées, de gagner en performance en évitant le tri imposé par un merge, d’afficher la date du jour dans un nom de fichier, dans un titre, et encore plus de chose.

Mais il y a des pièges. Comment s’assurer que les valeurs obtenues ne soient pas tronquées, ou encore pire, involontairement modifiées ? Comment repérer les valeurs présentent uniquement dans les formats mais pas dans les données ?

Dans ce cours, on part de la base afin de savoir choisir la bonne fonction et le bon format/informat en fonction de son besoin. À la fin de la première partie, vous saurez déjà comment convertir du caractère au numérique… En programmation, le diable se cache dans les détails. Dans la seconde partie, nous verrons tous ces cas particuliers qui font la richesse mais aussi la difficulté de ces fonctions. Les utilisateurs SAS débutants comme les programmeurs expérimentés y trouveront leur compte.

Le coupon de promotion pour le lancement de ce cours est valable jusqu’au 15 décembre 2022 : UPGRADE2022

et partager l’information à un ami ! Code promo : UPGRADE2022

h1

La fonction CATQ pour concaténer tout en ajoutant des guillemets avec SAS 9.3 et plus

février 23, 2019

La fonction catq est disponible depuis SAS 9.3. La particularité de cette fonction est de pouvoir ajouter des guillemets simples (single quotes) ou des guillemets doubles (double quotes) autour des différentes valeurs à concaténer.

Un des avantages de la fonction catq est de pouvoir travailler autant avec les valeurs numériques qu’avec les valeurs caractères. On fera néanmoins attention aux valeurs infinies comme 1/3.

Exemple 1

data catq;
    x=catq('1' ,'ABC ',2," EFG",' ');
    put x=;

    x=catq('2' ,'ABC ',2," EFG",' ');
    put x=;
run;

Dans ce premier exemple, on voit que le 1 permet d’ajouter des guillemets simples alors que le deux permet d’ajouter des guillemets doubles. Dans le cas présent, seules les valeurs caractères ont des guillemets.

x='ABC ' 2 ' EFG' ' '
 x="ABC " 2 " EFG" " "

Exemple 2

data catq;
   x=catq('1'     ,'ABC ',2," EFG",' '); 
   put x=;

   x=catq('1a'    ,'ABC ',2," EFG",' '); 
   put x=;
 
   x=catq('1c'    ,'ABC ',2," EFG",' '); 
   put x=;
   
   x=catq('1ac'    ,'ABC ',2," EFG",' '); 
   put x=;
run;

Dans ce second exemple, on voit que la lettre a pour que toutes les valeurs soient entre guillemets, y compris les valeurs numériques.

Si on souhaite ajouter la virgule (comma) entre les différentes valeurs à concaténer avec la lettre c, il faudra impérativement garder la lettre a.

 x='ABC ' 2 ' EFG' ' '
 x='ABC ' '2' ' EFG' ' '
 x=ABC ,2, EFG,
 x='ABC ','2',' EFG',' '

Exemple 3

Une autre manière d’ajouter la virgule comme séparateur entre les valeurs est d’utiliser la lettre d (delimiter) et de préciser le séparateur dans le second argument de la fonction ; cet argument est optionnel et ne servira qu’avec la lettre d.

data catq;
   x=catq('c','ABC ',2," EFG",' '); 
   put x=;

   x=catq('d',',','ABC ',2," EFG",' '); 
   put x= /;
  
   x=catq('1ac','ABC ',2," EFG",' '); 
   put x=;

   x=catq('1ad',',','ABC ',2," EFG",' '); 
   put x=;
run;

Nous obtenons le même résultat qu’on utilise c ou d avec l’argument optionnel. La lettre d offre juste plus de possibilités.

 x=ABC ,2, EFG,
 x=ABC ,2, EFG,
 x='ABC ','2',' EFG',' '
 x='ABC ','2',' EFG',' '

Exemple 4

Lorsqu’on n’a pas besoin des guillemets autour des différentes valeurs à concaténer, la fonction catq se rapproche de la fonction catx.

data catq;  
   x=catq('d',',','ABC ',2," EFG",' '); 
   put x=/;
   
   x=catq('ds',',','ABC ',2," EFG",' '); 
   put x=;
   
   x=catx(',','ABC ',2," EFG",' ');
   put x=/;
   
   x=catq('dt',',','ABC ',2," EFG",' '); 
   put x=;
run;

Pour enlever les leading et trailing blanks avec la fonction catq, on ajoutera la lettre s (strip).
Pour uniquement enlever les trailing blanks avec la fonction catq, on ajoutera la lettre t (trim).

 x=ABC ,2, EFG,
 x=ABC,2,EFG
 x=ABC,2,EFG
 x=ABC,2, EFG

Aller plus loin

La fonction dispose d’autres arguments pour travailler avec les literals (lettre n), pour afficher les valeurs en hexadecimal (lettre x), pour utiliser une tabulation horizontale comme séparateur (lettre h), etc.
Toutes les informations sont disponibles dans la documentation en ligne : http://support.sas.com/documentation/cdl/en/lefunctionsref/63354/HTML/default/viewer.htm

À lire aussi

h1

A partir de quelle lettre y a-t-il une différence : la fonction compare

mai 25, 2015

La fonction COMPARE retourne le nombre zéro si aucune différence n’existe entre deux chaînes de caractères. Sinon elle retourne la position la position du premier caractère différent.

Dans l’exemple ci-dessous, deux datasets sont créés. Une fois combinés, on s’intéresse à la différence entre la variable LABEL_ONE du premier dataset et la variable LABEL_TWO du second dataset. La première différence a lieu sur la deuxième lettre. La variable DIFF prend donc la valeur 2.

data one;
   length start $8 label_one $8;
   start='1';
   label_one='ABC';
run;

data two;
   length start $8 label_two $8;
   start='1';
   label_two='AbC';
run;

data diff;
   merge one two;
   by start;
run;

data diff;
   set diff;
   diff=compare(label_one,label_two);
run;

proc print data=diff;
run;

Vous pouvez ajouter un troisième paramètre dans la fonction si vous ne voulez pas tenir compte des différences de majuscule, de blancs de début de chaîne de caractère,…

Dans quel cas utiliser cette fonction ? Si vous réalisez un rapport listant la différence entre deux valeurs pour pouvoir ensuite les corriger, vous pouvez utiliser cette fonction pour préciser à partir de quel moment la couleur devra changer.

Pour en savoir plus : la documentation SAS 9.2

h1

Lister fichiers et répertoires sous UNIX

novembre 2, 2013

La fonction call system permet dans le cas présent de stocker du code Unix pour rechercher des fichiers dans des répertoires données. Le résultat de la recherche est stocké dans un fichier .txt qui est lu dans une étape data.

1. Créer une macro variable pour stocker le chemin d’accès de la bibliothèque WORK

Le chemin d’accès à la bibliothèque WORK est extrait avec la fonction système PATHNA?E et est stocké dans la macro variable WORKDIR. Ce chemin d’accès sera celui où sera sauvegardé le fichier .txt de la recherche.

%let workdir=%sysfunc(pathname(work));

2. Utiliser call symput pour appeler la commande find d’UNIX 

La commande find est suivie de trois composants :

  • le chemin d’accès au(x) fichier(x) d’entrée. L’astérisk indique que tous les sous répertoire du répertoire PROJET sont consultés
  • le chemin d’accès au fichier final (ici resultat.txt) où sera stocké le résultat de la recherche. Dans l’exemple, le fichier est stocké de manière temporaire dans le répertoire utilisé par la bibliothèque WORK de SAS.
  • La page anglaise de Wikipedia http://en.wikipedia.org/wiki/Find explique que le code 2>/dev/null supprime des messages d'erreurs liés à des droits d'accès.

« If you’re doing this as a user other than root, you might want to ignore permission denied (and any other) errors. Since errors are printed to stderr, they can be suppressed by redirecting the output to /dev/null. »

Dans le second appel le double >> permet d’ajouter au fichier existant le résultat de la recherche au lieu de remplacer l’ancien.

data _null_;
   call system ("find c:/projet/*/demographie.sas7bdat > &workdir./resultat.txt 2>/dev/null
                      c:/project/*/laboratoire.sas7bdat >> &workdir./resultat.txt 2>/dev/null");
run;

L’étape data  sert à lire le fichier .txt et de la trocker dans un dataset (ici REF) via infile/input. Des options à l’instruction infile peuvent être ajoutées pour lire le fichier correctement.

data ref (keep=);

   infile "&workdir./resultat.txt" ;*lrecl=2000 truncover firstobs=1;

   input pathdsn $1-100;

run;
h1

Passer de CLASS CLAS à « CLASS » « CLAS » dans une macro variable

février 1, 2013

Mettre toutes les mots contenus dans une macro variable entre guillemets (quote en anglais) est un tâche plus fréquente qu’elle n’y paraît.
Une vois le code écrit, il est souvent plus rapide de faire du copier/coller et ensuite de modifier. Voici un exemple où DSN=CLASS CLAS sert à créer DSN_QUOTE= »CLASS » « CLAS ».

1. Exemple dans une macro

Dans l’exemple, la macro est PRINTDSN. Elle a pour tâche d’imprimer dans la log tous les datasets présents dans la bibliothèque SASHELP qui sont cités dans le paramètre de macro DSN, s’ils existent.

%macro printdsn (dsn=);

%let dsn      =%upcase(&dsn.);
%let dsn_quote=%sysfunc(tranwrd(%nrstr(%")&dsn.%nrstr(%"),%str( ),%str(" ")));

proc sql;
 create table ref as
 select memname
 from dictionary.tables
 where upcase(libname)='SASHELP' and
       upcase(memname) in (&dsn_quote.);
quit;

data _null_;
 set ref;
 call execute ('proc print data=sashelp.' || memname || ';');
 call execute ('run;');
run;
%mend printdsn;
%printdsn(dsn=class clas);

Pour ma part j’ai pris l’habitude de mettre le contenu des macros paramètres en majuscule, et ce dès le début du programme, sauf besoin spécifique contraire. Ceci explique la ligne %let dsn=upcase(&dsn.);

De plus j’ai pris l’habitude de rajouter le suffixe _quote au nom de la macro variable. Dans notre exemple il y a la macro variable DSN mise en majuscule. Cette variable est ensuite mise entre guillemets.

La macro fonction %sysfunc() permet d’utiliser la fonction tranwrd dans une expression macro. La fonction tranwrd est composée de trois paramètres :

  1. le texte d’origine entre guillemets
  2. le partie de texte à remplacer dans cette chaîne de caractères
  3. le texte de remplacement

2. Le même exemple sans macro

L’exemple est présenté dans une macro. Pour tester le code, un simple %let et %put feront l’affaire. Le résultat s’affiche alors dans la log.

%let dsn=CLASS CLAS;
%let dsn_quote=%sysfunc(tranwrd(%nrstr(%")&dsn.%nrstr(%"),%str( ),%str(" ");
%put &dsn_quote.;
h1

Protégé : Newsletter Exercices – n°1 : Solution

juillet 14, 2012

Cet article est protégé par un mot de passe. Pour le lire, veuillez saisir votre mot de passe ci-dessous :

h1

Plusieurs formats pour une variable numériques – passer à une variable caractère avec la fonction PUTN

octobre 14, 2010

Découvrez le cours de novembre 2022 : Les fonctions put et input – un sujet épineux

Dans cet article que vous propose une illustration de la fonction PUTN. En effet une variable numérique peut contenir des groupes de valeurs. Chaque groupe de valeurs se réfère à un format donnée. Le nom de ces formats est disponible dans une autre variable. La question est alors comment puis-je créer une variable caractère équivalent simplement, sans boucle, sans if-then, etc. La solution : la fonction PUTN. Voici un exemple pour illustrer le propos.

1. Le problème en exemple

Dans cet exemple, deux formats numériques AGE et SEX exitent.

proc format;
value age 11-13=’11-13′
14-16=’14-16′;
value sex 1=‘Male’
2=‘Female’;
run;

Dans un data set, ONE, trois variables existent :

  • CRITERIA : les critères sont AGE et SEX dans l’exemple.
  • CODLST : le nom des formats qui expliquent les valeurs numériques sont enregistrés dans la variable CODLST.
  • VALN: les valeurs numériques associées aux critères sont disponibles dans la variable VALN.

data one;
length criteria $8 codlst $8;
input criteria $ codlst $ valn;
age age 12
sex sex 1
;
run;

L’objectif est de créer une variable VALC qui contienne l’équivalent alphanumérique de VALN (la valeur donnée dans le label du format).

2. La solution proposée : PUTN

data two;
set one;
length valc $20;
VALC=putn(valn,codlst);
run;

3. Le résultat attendu

criteria codlst valn valc

age      age    12   11-13
sex      sex    1    Male

Ici les formats sont tous numériques. La fonction PUTN est utilisée.
Pour des formats alphanumériques, il faudra se servir de la fonction PUTC.

Allez plus loin

Découvrez le cours de novembre 2022 : Les fonctions put et input – un sujet épineux

h1

Protégé : Newsletter Exercice – n°1 : Enoncé

juillet 6, 2010

Cet article est protégé par un mot de passe. Pour le lire, veuillez saisir votre mot de passe ci-dessous :

h1

Comparer deux chaînes de caractères : A quel endroit se situe la première différence ? (la fonction COMPARE)

juin 20, 2010

Occasionnellement il peut s’avérer utilise de comparer deux chaînes de caractères et de savoir plus précisément où se situent les différences. La fonction COMPARE peut vous aider dans cette tâche.

En effet, la fonction COMPARE indique à quel endroit se situe la première différence entre les deux chaînes. Voici un exemple.

1. Le code

data one;
comp1=compare(‘abc’,‘abc’);
comp2=compare(‘ABc’,‘ABC’);
comp3=compare(‘A1C’,‘ABC’);
comp4=compare(‘ABC’,‘A1C’);
run;

proc print data=one;
run;

2. Interprétation des différents cas

Dans le premier cas (comparer abc à abc), la fonction retourne une valeur 0 car il n’y a aucune différence. Comme la plupart des fonctions SAS, la valeur zéro indique qu’aucune différence entre les deux chaînes n’a été identifiée.

Dans le second cas (comparer ABc à ABC), la fonction retourne une valeur 3 car la lettre c située en troisième position est dans un cas écrite en minuscule et dans un cas écrite en majuscule. La fonction est sensible à la case à moins d’ajouter des options dans le troisième paramètre de la fonction.

Dans le troisième cas (comparer A1C à ABC), la fonction retourne une valeur 2 car la première différence se trouve au niveau du second caractère.

Dans le quatrième et dernier cas (compare ABC à A1C), le premier et le second texte ont seulement été inversé. La fonction retourne une valeur négative -2 car si on trie les données le chiffre 1 apparaît avant la littre B. Si comme moi, ce qui vous intéresse est uniquement l’endroit où se situe la différence, vous pouvez prendre la valeur absolue en encadrant la réponse dans une fonction ABS().

Lectures complémentaires :

h1

Une petite histoire de macro : compter le nombre de mots dans un paramètre de macro

avril 11, 2010

Il est courant de devoir compter le nombre de mots dans un paramètre de macro. Il est par exemple possible de vouloir créer une boucle pour travailler chacun des termes contenu dans cette macro de manière séparée.

Voici donc l’histoire d’une mini macro qu’on nommera CNT_WRD qui crée une macro variable TOT_WRD renvoyant le nombre de mots contenu dans le paramètre TXT.

Ceci est pour vous l’occasion de voir ou revoir un raisonnement possible dans la construction d’une macro sous SAS.

1. Préciser ses besoins, une rapide « spécification »

La macro CNT_WRD composée d’un seul paramètre retournera dans une macro variable TOT_WRD le nombre de mots contenus dans le texte donné dans le paramètre de macro.

Ici on considérera comme mot, tout terme séparé par au moins un blanc.

Si le paramètre de macro est vide, la macro ne devra pas afficher de message d’erreur et la macro variable TOT_WRD sera égale à 1. Par défaut, aucune valeur ne sera entrée dans le paramètre TXT.

La macro variable doit pouvoir être utilisable à l’extérieur de la macro (macro variable globale).

2. Tester la fonction COUNT dans une étape data

La fonction COUNT permet de comptabiliser certains caractères et donc de répondre à ce type de besoin. En fait, cette fonction ne compte pas le nombre de mots mais compte le nombre de caractères définis par le second élément dans la fonction; dans notre cas, elle comptera le nombre de blancs. Il faut donc ajouter 1 au total.

Voici un exemple dans une étape data.

data _null_;
tot_wrd=1+count(‘mot1 mot2’,‘ ‘);
put tot_wrd=;
run;

Dans la log, vous pouvez voir que cnt_wrd=2.

Mais cela ne suffit pas pour gérer les blancs multiples et les blancs aux extrémités. Car si vous avez plus d’un blanc entre chaque mot, chacun sera compté. Il faut donc les enlever au préalable (avec la fonction COMPBL ici). Les blancs de début et fin peuvent s’enlever au moyen de la fonction STRIP.

data _null_;
tot_wrd=1+count(strip(compbl(‘ mot1 mot2 ‘)),‘ ‘);
put tot_wrd=;
run;

Mais que ce passe t-il si notre texte à compter est vide ? TOT_WRD sera égal à 1. Il faut donc ajouter le 1 au total que si le texte à analyser n’est pas vide.

data _null_;
length txt $200;
txt=;
if txt ne ‘ ‘ then tot_wrd=1+count(strip(compbl(txt)),‘ ‘);
put tot_wrd=;
run;

3. Créer la macro

Comme indiqué dans le dernier point, on travaille ici de manière conditionnelle. Si le paramètre de macro TXT est vide, la macro variable CNT_WRD nouvellement créée prend la valeur zéro. Sinon, On passe par la fonction COUNT.

Comme il n’existe pas d’équivalent aux fonctions COUNT et COMPBL en langage macro, il faut encadrer chacune d’elle dans une fonction macro SYSFUNC.

Ici on notera que la fonction STRIP n’apparaît pas. Les blancs de début et de fin en langage macro n’ont aucun impact.

%macro cnt_wrd(txt=);

%global tot_word;

%if &txt.= %then %let tot_wrd=0;
%else %let tot_wrd=%eval(1+%sysfunc(count(%sysfunc(compbl(&txt.)),%str( ))));

%mend cnt_wrd;

Pour représenter un blanc dans une étape data, il suffit d’utiliser des guillemets. En langage macro, on fait appel à la fonction %STR(). Il faudra ne pas oublier d’ajouter un blanc entre les parenthèses.

Afin d’ajouter 1 au résultat de la fonction COUNT, il faut utiliser la macro fonction %EVAL. Le contenu des macro variables sont sinon tous interprétés comme du texte, qu’il s’agisse de nombres ou pas.

Enfin, pour que cette macro variable TOT_WRD soit utilisable en dehors de la macro, il faut qu’elle soit globale. Hors par défaut, une macro variable créée dans une macro est locale, c’est-à-dire n’existe que le temps de la macro. L’instruction %GLOBAL TOT_WRD; résouds le problème.

4. Tester la macro dans le cadre de sa validation

Que se passe t-il quand on ne change pas la valeur par défaut du paramètre de macro ?

%cnt_wrd;
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand le paramètre de macro TXT est vide de texte ?
%put Valeur de TOT_WRD: &tot_wrd;

%cnt_wrd(txt=);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il lorsqu’il n’y a qu’un mot?

%cnt_wrd(txt=mot1);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand il y a plusieurs mots ?

%cnt_wrd(txt=mot1 mot2 mot3);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand il y a des blancs multiples entre les mots, en début et à la fin ?

%cnt_wrd(txt= mot1 mot2 mot3 );
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand il y a des blancs multiples entre les mots, en début et à la fin ?

%cnt_wrd(txt=mot1 mot2);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand la macro est appelée plusieurs fois ?

%cnt_wrd(txt=mot1 mot2);
%put Valeur de TOT_WRD: &tot_wrd;
%cnt_wrd(txt=mot1);
%put Valeur de TOT_WRD: &tot_wrd;

Lecture complémentaire

h1

Une fonction LIBREF au résultat inattendu

mars 23, 2010

La fonction LIBREF vérifie l’existence d’une bibliothèque. Vu que la réponse attentue est oui ou non, on pourrait s’attendre à une résultat binaire avec zéro pour non et un pour oui. Dans les faits, cette fonction retourne zéro pour oui et toute autre valeur signifie non.

Voici un exemple.

1.  Contexte, exemple

Vous cherchez à savoir si le chemin d’accès défini dans un  paramètre de macro peut servir de bibliothèque. Une solution est de tenter de créer la bibliothèque et ensuite de vérifier si la bibliothèque a été créée ou non.

2. Le programme

Dans l’exemple qui suit, une macro TEST est créée. Elle a un paramètre DSNPATH=. Le chemin d’accès donné dans ce paramètre est utilisé pour créé la bibliothèque INLIB.

Ensuite pour les besoins de l’exemple, un message est ajouté dans la log au moyen des instructions %PUT.

  • Tout d’abord, est indiqué dans la log la valeur prise par le paramètre de macro DSNPATH.
  • Puis, la valeur prise par la fonction LIBREF est affiché dans la log.

Afin de pouvoir utiliser cette fonction hors d’une étape data ou d’une procédure PROC SQL, il faut l’englober dans une macro fonction %SYSFUNC().

En fin de macro la référence à la bibliothèque est supprimée.

%macro test(dsnpath=);
libname inlib « &dsnpath. »;
%put MESSAGE: DSNPATH= &dsnpath.;
%put MESSAGE: Voir le résultat de la fonction LIBREF dans la log: %sysfunc(libref(inlib));
libname inlib;
%mend test;

Le premier appel de macro se fait avec un chemin d’accès valid. Tandis que le second appel de macro utilise un chemin d’accès erroné.

%test (dsnpath=C:/sasref);
%test (dsnpath=C:/sasre);

3. La log

Lorsque le chemin d’accès est correct, la fonction LIBREF retourne la valeur 0.

Quand le chemin d’accès n’est pas correct, la fonction LIBREF retourne une valeur différente de zéro. Dans l’exemple, il s’agit de la valeur -70008.

Lectures complémentaires

Autres articles sur %SYSFUNC

SAS Online Doc

  • Summary Descriptions and Syntax
  • LIBREF Function
h1

Protégé : Newsletter Mars : solution

mars 1, 2010

Cet article est protégé par un mot de passe. Pour le lire, veuillez saisir votre mot de passe ci-dessous :

h1

Les expressions régulières, un exemple avec des crochets à remplacer

février 8, 2010

Les expressions régulières donnent à SAS plus de flexibilité dans le travail des chaînes de caractères que les fonctions classique comme INDEX, TRANWRD, SUBSTR ou encore SCAN. Voici un exemple de code remplaçant le contenu dans des crochets.

1. Le data set qui sert d’exemple

A la base on a un fichier TEXT avec une ligne d’observation et une variable TEXT de longueur 50.

TEXT est égal à : ab CD ef [gh] [] [kl] mn [op].

data text;
length text $50;
text=‘ab CD ef [gh] [] [kl] mn [op]’;
run;

2. L’étape data est divisée en trois parties

On veut ici remplacer le contenu entre crochets par un seul et unique x.

data text (drop=rx:);
set text end=eof;

*1. Créer RX1;
retain rx1 0;
if _N_=1 then rx1=rxparse(« ‘[‘ ^'[]’ *’]’ to ‘[x]' »);

*2. Créer NEW_TEXT;
length new_text $50;
call rxchange (rx1,99999, text, new_text);

*3. Supprimer RX1;
if eof then call rxfree(rx1);

run;

Voici le résultat attendu :


3. La premier partie du programme, création de la variable RX1

Extrait du code :

*1. Créer RX1;
retain rx1 0;
if _N_=1 then rx1=rxparse(« ‘[‘ ^'[]’ *’]’ to ‘[x]' »);

Dans un premier temps la variable RX1 est créée au moyen de la fonction RXPARSE qui ne contient qu’un paramètre dont les valeurs sont entre guillemets, ici des guillemets doubles. Il s’agit de remplacer une chaîne de caractères

  • qui commence par un crochet ouvrant: ‘[‘
  • qui termine par un crochet fermant : ‘*]’
  • qui ne contient pas à l’intérieur d’autres paires de crochets : ^'[]’

par

  • un x entre crochet : to ‘[x]’

L’opération étant identique pour toutes les observations du data set, il suffit de l’effectuer l’opération quand _N_=1 et d’étendre le résultat à toutes les observations avec un RETAIN rx1 0;. Cela s’avère très bénéfique pour les grandes data sets en terme de performance du programme.

4. La seconde partie du programme, création de la variable NEW_TEXT

Extrait du code :

*2. Créer NEW_TEXT;
length new_text $50;
call rxchange (rx1,99999, text, new_text);

Une nouvelle variable NEW_TEXT de longueur 50 est créée. La fonction CALL RXCHANGE qui sert à la définir est composée de 4 paramètres.

  1. Tout d’abord RX1 qui donne la chaîne de caractère d’origine et celle par laquelle elle doit être remplacée.
  2. Ensuite 99999 est un large nombre qui précise le nombre maximum de changements qui peuvent être fait.
  3. TEXT est la variable d’origine
  4. NEW_TEXT est le nom de la nouvelle variable.

Notez que pour changer la variable existante plutôt que de créer une nouvelle variable, il vous suffit de limiter la fonction aux trois premiers paramètres.

call rxchange (rx1,99999, text);

5. La troisième et dernière partie, suppression de la variable RX1

Extrait du code :

*3. Supprimer RX1;
if eof then call rxfree(rx1);

Afin de libérer de l’espace en arrière plan, la fonction CALL RXFREE est appelée en fin de programme pour supprimer RX1 en tant qu’indicateur d’expression régulière.

Lecture complémentaire :
Some Practical Ways to Use the New SAS Pattern-Matching Functions, Mike Rhoads, Westat, Rockville, MD (SAS version 6.11 et SAS 6.09 Experimental)

h1

Créer une variable numérique à partir d’une variable caractère (fonction INPUT avec point d’interrogation)

octobre 17, 2009

Vous avez des nombres et du texte sauvegardés dans une variable caractère dans une table SAS et vous voulez sauvegarder les données numériques dans une variable numérique sans avoir dans la log une indication d’erreur (_ERROR_=1) pour les valeurs non compatibles. Comment adapter la fonction INPUT ?

1. Les données pour l’exemple

Pour l’exemple,  nous avons un dataset appelé CHAR avec une variable caractère, X_CHAR et 5 observations.

data char;
length x_char $10;
input x_char $ 1-10;
datalines;
-1.3
– 5
5.3.2
18.9
AB
;
run;

2. Le résultat attendu

Nous voudrons que la première et la quatrième observation soient converties en nombre. En effet,les trois autres valeurs ne sont pas convertibles.

  • La seconde observations est non valide à cause de l’espace séparant le signe moins et le nombre 5.
  • La troisième observation a plus d’un point
  • La dernière observation est un texte.

3. La version traditionnelle

La fonction INPUT permet de passer d’une variable caractère à une variable numérique. Elle est composée de deux paramètres : le nom de la variable caractère à convertir (ou une valeur entre guillemets) et l’informat qui permet d’interpréter les valeurs de la variable.

data char_num;
set char;
x_num=input(x_char,20.6);
run;

Malheureusement, SAS n’est pas totalement satisfait de cette action pour les valeurs ne répondant pas aux critères de l’informat.

input_withoutquestionmark

4. Une log propre grâce au point d’interrogation

Le double point d’interrogation précédent le nom de l’informat empêchera la log d’avoir la note. Bien sûr, cela n’a d’intérêt que si vous avez de bonnes raisons d’ignorer ce message d’erreur. Le cas contraire, vérifiez vos données.

data char_num;
set char;
x_num=input(x_char,??20.6);
run;

Note : si la fonction INPUT est utilisée dans l’option de data set WHERE, un WARNING apparaît.

data char_num ;
set char (where=(input(x_char,20.6)=18.9));
run;

input_warning

Ce warning ne peut être enlevé avec le point d’interrogation. Il crée même une erreur dans la log.

input_error

Lecture complémentaire

h1

Alterner les couleurs de fond dans un tableau : une ligne sur deux (ODS et PROC REPORT)

août 30, 2009

Ces semaines passées, je vous ai proposé une syntaxe pour changer le style des cellules d’un tableau généré sous SAS avec PROC REPORT. Aujourd’hui, je vous propose une variante permettant de changer la couleur de fond une ligne sur deux. L’exemple utilise une sortie PDF. Le programme peut s’appliquer aux sorties RTF et TAGSETS.EXCELXP.

1. Le programme

Dans PROC REPORT, l’instruction CALL DEFINE contenu entre les instructions COMPUTE et ENDCOMP permet de modifier le style des lignes dans un tableau.

La notion de RETAIN : Dans l’exemple qui suit une variable nommée CNT est créée avec un RETAIN implicite. Le changement de couleur de fond est fonction de la valeur prise par cette variable. Vous pouvez également utilisée une variable déjà existante dans le data set lu.

La foncton MOD() : Le modulo est le résidu d’une division. La fonction MOD() avec un modulo 2 permet de distinguer les valeurs pairs des valeurs impaires. Ici à chaque fois que la valeur CNT a une valeur pair, le fond est mis en gris.

ods listing close;
ods pdf file=‘C:/sasref/zebre.pdf’;
proc report data=sashelp.class nowd;
columns name age;
define name / display;
define age / display;
compute name;
cnt+1;
if mod(cnt,2) then call define (_row_,‘style’,‘style=[background=lightgrey]’);
endcomp;
run;
ods pdf close;
ods listing;

2. Le résultat

zebre

Lectures complémentaires

h1

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

mai 28, 2009

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

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

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

options mprint;

%macro test (multival=);

%mend test;

%test (multival=Alfred William);

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

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

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

run;

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

2. Comment ajouter guillemets et virgules ?

2.1 Un mot

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

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

La macro donne alors :

%macro test (multival=);

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

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

run;

%mend test;

%test (multival=Alfred);

2.2 Plus d’un mot

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

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

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

%macro test (multival=);

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

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

run;

%mend test;

%test (multival=Alfred William);

2.3 Plus d’un mot mis en majuscule

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

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

Cela donne :

%macro test (multival=);

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

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

run;

%mend test;

%test (multival=Alfred William);

Lectures complémentaires

h1

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

mai 18, 2009

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Lectures complémentaires

Sur le blog www.sasreference.fr

Online Doc

  • DO WHILE Statement
  • DO UNTIL Statement
h1

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

avril 30, 2009

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

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

1. Lire dans la LOG l’information

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

proc options option=linesize;
run;

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

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

2. Sauvegarder l’information dans une macro variable

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

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

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

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

h1

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

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