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
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.
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.
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).
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
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 printdata=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.
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.
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().
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é.
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.
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;
Ce warning ne peut être enlevé avec le point d’interrogation. Il crée même une erreur dans la log.
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 reportdata=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;
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.
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.
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.
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).
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.
datano_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.
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 printdata=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.
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.
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.
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).
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.
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)
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.
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.
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 :
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;
Scanner le contenu d’un texte et identifier le xème « Mot » est possible sous SAS grâce à la fonction SCAN. Je vous propose dans un premier temps de voir les différents paramètres de la fonction. Puis dans un second temps, vous aurez à disposition quelques exemples documentés à tester soi-même.
Deux exemples d’applications :
Définir une condition (IF THEN par exemple) selon la valeur prise par le mot trouvé.
Sauvegarder le « mot » dans une nouvelle variable.
1. Trois paramètres pour la fonction SCAN
La fonction SCAN est composée de trois paramètres.
Le texte à scanner
La position du mot recherché
Le symbole délimitant les mots dans le texte
1.1 Le texte à scanner est donné dans le premier paramètre
Le texte à scanner peut-être une chaîne tapée manuellement entre guillemets. Mais il est plus probable que vous souhaitiez opérer l’opération pour chacune des observations contenues dans une variable caractère.
Il s’agit alors de nommer la variable.
Rappel : lorsqu’une variable est nommée, il ne faut jamais mettre son nom entre guillemets. La fonction SCAN ne fait pas exception.
1.2 La position du mot recherché est définie dans le second paramètre
Des nombres entiers : la position du mot est donnée par un nombre entier.
1 correspond au premier mot de la chaîne de caractères;
2 au deuxième, etc.
Les valeurs négatives : il est en effet possible d’utiliser des valeurs négatives pour définir la position du mot. De quoi s’agit-il ? Tout simplement, au lieu de commencer par le début de la chaîne, SAS commence par la fin.
-1 correspond au dernier mot,
-2 à l’avant dernier mot, etc.
1.3 Le délimiteur apparaît en troisième
Trouver des « mots » au sens large du terme : En langage courant, un mot est un ensemble de lettres séparées par un espace. Avec la fonction SCAN, le symbole séparant les mots est libre. L’utilisateur se chargera de définir ce symbole.
Le symbole séparant les mots est à donner entre guillemets. A titre d’exemple, il peut s’agir de tirets bas (underscore en anglais), de barre inclinée (slash en anglais), de blancs (blank en anglais).
2. La fonction SCAN par l’exemple
Exemple 1 : Dans ce premier exemple, une variable NAME contient 5 observations.
data dict; length name $8; input name $; datalines;
PAT_ID
COUNTRY
REC_ID
VISIT
VISIT_DT
; run;
Grâce à la première condition, les observations se terminant par _DT sont sauvegardées dans le data set DT_VAR. Il n’y a que la variable VISIT_DT.
Avec la seconde condition, les observations commençant par VISIT_ sont envoyées dans le data set VISIT_VAR.
data dt_var visit_var; set dict; if scan(name,-1,‘_’)=‘DT’thenoutput dt_var; if scan(name,1,‘_’)=‘VISIT’then output visit_var; run;
Exemple 2 : Dans ce second exemple, une variable PATH a 3 observations.
data path_lst;
path=‘c:/sasref/projet123/study1/pgm’; output;
path=‘c:/sasref/projet123/study9/pgm’; output;
path=‘c:/sasref/projet444/study2/pgm’; output; run;
Dans ce premier cas, les observations contenant le mot proj123 en troisième niveau dans le chemin d’accès sont gardées.
data projet123; set path_lst; if scan(path,3,‘/’)=‘projet123’;*then output; run;
Dans ce second cas, une nouvelle variable est créée. Elle contient le numéro de l’étude disponible en quatrième position dans le chemin d’accès fourni dans la variable PATH.
data study_var;
study=scan(path,4,‘/’); run;
Je vous donne rendez-vous demain samedi pour un article sur l’option FMTSEARCH.
La quantité d’espace alloué pour une observation dans un data set SAS peut aller jusqu’à 32 767 octets (byte en anglais). Pour m’amuser, j’ai voulu tester. Pour ce faire, j’ai procédé en trois étapes :
J’ai créé une variable de 32 767 caractères et j’ai imprimé sa seule valeur dans un fichier .TXT.
Puis, j’ai voulu voir comment se déroulait le passage de 32 767 caractères d’un fichier .TXT dans une seule observation d’un data set SAS.
Enfin, pour visualiser le tout, j’ai imprimé cette observation dans un fichier .RTF.
Note : La longueur (length) est le mot utilisé en SAS pour parler de la quantité d’espace alloué à une observation. Seules les variables de type caractères (character) peuvent avoir jusqu’à 32 767 octets. Les variables numériques en ont, en effet, 8 au maximum. Un octet permet de stocker un caractère d’une variable texte. Pour plus de précisions sur l’octet, reportez-vous à l’article « 9 points autour de la notion d’octet« .
Note : La longueur allouée est identique pour toutes les observations d’une même variable. Si la longueur de la variable n’est pas explicitement donné, SAS utilise la longueur de la première observation. Avec un input file, seuls 8 octets sont attribués (SAS Online Doc. : SAS Variable Attributes »).
data one; input x $; datalines;
ABC
ABCDEFGHIJKLMN
; run;
data two;
x=‘ABC’; output;
x=‘ABCDEFGHIJKLMN’; output; run;
data three;
x=‘ABCDEFGHIJKLMN’; output;
x=‘ABC’; output; run;
Dans le premier exemple, la longueur sera de 8. La seconde observation sera donc coupée.
ABC
ABCDEFGH
Dans le second exemple, la longueur est définie par la première observation. Il s’agit donc d’une longueur de 3. La seconde observation est coupée et ne garde que les trois premiers caractères.
ABC
ABC
Dans le troisème exemple, la longueur est également définie par la première observation. Elle est donc cette fois de 14. Aucune des deux observations n’est coupée.
ABCDEFGHIJKLMN
ABCDEFGHIJKLMN
Cette valeur est changeable. Il s’agit de modifier l’attribut LENGTH d’une variable donnée dans un data step. La valeur est définie soit à l’instruction LENGTH, soit à l’instruction ATTRIB.
1. Imprimer 32 767 caractères dans un fichier .TXT
Dans l’exemple ci-dessous, un fichier .TXT est créé. Il contient 32 767 caractères venant d’une seule et même observation.
Une instruction LENGTH définissant le type et la longueur de la variable : Dans cet exemple, une variable TEST_VAR est créée. Il s’agit d’une variable caractère. Une longueur de 32 767 lui est assignée avec l’instruction LENGTH. Elle pourra donc contenir jusqu’à 32 767 octets par record.
Taper plus de 32 000 caractères, c’est long mais il y a la fonction REPEAT pour nous sauver : La valeur prise par le premier record de la variable TEST_VAR est donnée. J’ai choisi de répéter la lettre a 32 766 fois. Je dis bien 32 766 fois et non 32 765 fois car la fonction REPEAT ajoute à la valeur initiale ‘a’ 32 765 autres ‘a’, soit 32 765 + 1.
Ajouter un dernier caractère à notre valeur : A ces 32 766 lettres ‘a’, j’ai ajouté la lettre ‘b’ en faisant une concaténation grâce aux deux barres verticales. De cette manière, il sera possible de visualiser l’absence de coupure faite par SAS.
filename lgth_max ‘C:/sasref/lgth_max.txt’; data _null_; file lgth_max; length test_var $ 32767;
test_var=repeat(‘a’,32765)||‘b’; put test_var; run; filename lgth_max clear;
Ecrire le contenu de la variable dans un fichier externe : pour écrire les 32 767 caractères dans un fichier externe, SAS a besoin de trois instructions.
Ecrire du texte avec l’instruction PUT : L’instruction PUT est exécutée pour chaque observation de la variable TEST_VAR, c’est-à-dire une fois dans notre cas.
Diriger un texte vers une autre destination que la log avec l’instruction FILE : La valeur prise par la variable TEST_VAR est écrite dans un autre fichier. Cet autre fichier est désigné de manière indirecte dans l’instruction FILE. Je dis de manière indirecte car seul un nom figure dans l’instruction FILE, un nom désignant un fichier préalablement défini. On parle de FILEREF.
Caractériser un fichier de destination avec l’instruction FILENAME : Le FILEREF désignant la destination du texte à imprimer est défini dans l’instruction FILENAME. A la fin du programme, ce nom servant d’intermédiaire est supprimé pour pouvoir resservir et ainsi désigner un autre fichier ou chemin d’accès.
Pas besoin de créer un data set SAS ici : Dans le cas présent, nous avons besoin d’une étape DATA pour exécuter ce code mais nous n’avons pas besoin de créer un data set. Pour épargner la tâche de création d’un data set, le nom _NULL_ remplace le nom d’un data set.
2. Créer un data set SAS
Lire les données contenues dans un fichier externe : Une variable TEST_NEW est créée dans un data set nommé TEST_DS. Elle est de type caractère comme l’indique le symbole dollar ($) présent dans l’instruction INPUT.
Avant d’entrer une valeur dans cette variable, la longueur maximale autorisée est définie dans l’instruction LENGTH. Comme il s’agit d’une variable caractère, il faut ajouter le dollar.
Au lieu de saisir manuellement les valeurs dans le data step en introduisant le mot DATALINES, une instruction INFILE désigne le fichier où sont stockées les données.
Vérifier la valeur prise par l’attribut LENGTH de la variable TEST_NEW : La procédure PROC CONTENTS donnera un aperçu des caractéristiques des variables du data set TEST. Bref, cette procédure donnera accès aux méta données (metadata ou données sur les données). Cela comprend la longueur allouée à la variable TEST_NEW et le type de la variable (caractère dans ce cas précis).
proc contentsdata=test_ds; run;
3. Visualiser le data set dans un fichier .RTF
Seuls les 128 premiers caractères sont imprimables dans la fenêtre OUTPUT. Par contre, vous pouvez envisager d’autres destinations comme un fichier .RTF. Dans l’exemple, on joue avec les instructions ODS (Output Delivery System).
D’une part, la redirection vers la fenêtre output est stoppée le temps de l’impression, via les instructions ODS LISTING.
D’autre part, les 32 767 caractères sont envoyés dans un fichier .RTF grâce aux instructions ODS RTF.
SAS effectue plusieurs lectures d’un programme. A la première lecture, c’est la compilation. A la seconde, c’est l’exécution. Connaître ces notions vous aidera à comprendre les exemples ci-dessous : pourquoi le premier code proposé ne fonctionne pas alors que les autres passent. Les fonctions PUT, VVALUE, le dictionnaire DICTIONARY.COLUMNS et le DATA _NULL_ serviront dans les exemples.
1. Un premier exemple avec la fonction PUT
Rappel sur la fonction PUT : Une fonction PUT permet de convertir une variable numérique en variable texte ou une variable texte en une autre variable texte. Elle est composée de deux paramètres. D’un côté, il y a la variable d’origine. De l’autre côté, il y a le format à appliquer sur cette variable d’origine. C’est donc la valeur sous forme formatée qui devient une valeur texte. Reportez vous à l’article « Convertir une variable caractère en numérique et inversement » pour plus de détails.
La phase de compilation : A la compilation, SAS vérifie que la variable d’origine et le format associé sont tous les deux du même type. Il faut qu’une variable numérique est un format qui s’applique à une variable numérique. De manière identique, il faut un format caractère pour une variable texte.
La phase d’exécution : Si on ne connaît pas à l’avance le type de la variable, on peut avoir envie de définir une condition : si la variable est numérique applique tel format, sinon applique tel autre format. Hors une condition IF/THEN n’est visible par SAS qu’à la phase d’exécution.
En d’autres termes, SAS tentera d’appliquer un format numérique à une variable numérique avant de regarder si la fonction PUT est définie dans une condition.
data import_excel; retain type ‘CHAR’;
study = ‘999’; output;
study = ‘888’; output; run;
data study_new; set import_excel; if type=‘NUM’then study_new=put(study,best.); else study_new=study; run;
Le résultat : Dans l’exemple, un format numérique (BEST.) est appliqué à une variable texte (STUDY). La première partie de la condition ne s’applique pas car le type de la variable n’est pas égal à NUM. Mais SAS cherche un format $BEST. qui n’existe pas. Il est obligé de s’arrêter là.
28 data study_new;
29 set ref;
30 if upcase(type)=’NUM’ then study_new=put(study,best.); —–
48 ERROR 48-59: The format $BEST was not found or could not be loaded.
31 else study_new=study;
32 run;
NOTE: The SAS System stopped processing this step because of errors. WARNING: The data set WORK.STUDY_NEW may be incomplete.
When this step was stopped there were 0 observations and 3 variables.
Un exemple où le type de la variable est inconnu : en important un fichier EXCEL (PROC IMPORT/MIXED=YES), le type de la variable sous SAS peut-être inconnu. La variable sera caractère si une cellule contient du texte. Sinon, elle sera numérique.
2. Une solution rapide
Une fonction Vxxx: la fonction VVALUE retourne une valeur texte. Elle utilise le format associé à la variable en interne pour construire la valeur sous forme formatée. La nouvelle variable aura une longueur de 200.
data study_new; set ref; if type=’NUM’ then study_new=vvalue(study); else study_new=study; run;
3. Une solution plus lourde mais pouvant s’appliquer à plusieurs variables
Une autre solution est de générer le code à exécuter. Si la variable est numérique, c’est l’instruction avec PUT qui apparaîtra, sinon c’est l’autre instruction. Cette approche fait appel à la notion de dictionnaire et de DATA _NULL_.
3.1 Créer un data set contenant le nom des variables et leur type à partir du dictionnaire (dictionary) appelé COLUMNS
La première étape consiste à créer un data set, nommé DICT_REF, contenant la variable STUDY et son type.
Choix du dictionnaire : Le dictionnaire (dictionary) COLUMNS est un data set de référence, créé de manière automatique par SAS. Il répertorie toutes les variables contenues dans tous les data sets de toutes les bibliothèques actives. Il contient donc une ligne par variable.
Chaque ligne du dictionnaire contient plusieurs informations caractérisant cette variable dont :
la bibliothèque d’origine (variable LIBNAME)
le data set d’origine (variable MEMNAME)
le nom de la variable (variable NAME)
le type de la variable (variable TYPE).
Prendre un sous-ensemble du dictionnaire : Ici seule la variable STUDY est utile. Elle provient du data set EXCEL_IMPORT sauvegardé de manière temporaire dans la bibliothèque WORK.
Mettre en majuscule : Le type de la variable est soit « num » soit « char », toujours en minuscule. Le nom de la variable peut avoir un mélange de majuscules et minuscules selon la manière dont est saisi le nom lors de sa création. Pour éviter des surprises, le nom de la variable et le type sont mis en majuscule grâce à la fonction UPCASE. L’avantage des dictionnaires, c’est qu’ils peuvent lister plus d’une variable.
proc sql; create table dict_ref as select upcase(name) as name,
upcase(type) as type from dictionary.columns where upcase(libname) = ‘WORK’and upcase(memname) = ‘EXCEL_IMPORT’and
upcase(name) = ‘STUDY’; quit;
3.2 Ecrire le code et l’appeler
La deuxième étape consiste à créer un programme nommé TMP_STUD.SAS donc le nom et l’emplacement est défini dans l’instruction FILENAME. Pour écrire dans ce fichier, l’instruction FILE est ajoutée dans le DATA _NULL_. Pour plus de précisions sur l’instruction PUT, reportez-vous à l’article « Ecrire un texte avec l’instruction PUT« .
filename stud ‘C:/sasref/tmp_stud.sas’;
data _null_; set dict_ref; file stud; put‘data study_new;’; put @3‘set excel_import;’; if type=‘NUM’then put @3‘study_new=put(‘ name ‘,9.);’; else put @3‘study_new=’ name ‘;’; put‘run;’; run;
%include stud; filename stud;
L’écriture du programme est fonction des informations contenues dans le DICT_REF. Si plus d’une variable est sélectionnée, il faudrait préciser deux choses :
Les instructions DATA et SET ne sont à écrire qu’une fois. Elles sont ajoutées lors de la première boucle fait en interne autour de l’étape DATA via « if _N_=1 ».
L’instruction RUN apparaît une fois en fin de programme. Il faut donc l’ajouter une fois le dernier record du fichier de référence atteint. L’option END= de l’instruction SET crée une variable interne prenant la valeur 0 pour tous les records sauf le dernier où elle prend la valeur 1. La condition est donc basée sur cette variable.
filename stud ‘C:/sasref/tmp_stud.sas’;
data _null_; set dict_ref end=eof; file stud; if _N_=1then do; put‘data study_new;’; put @3‘set excel_import;’; end; if type=‘NUM’then put @3‘study_new=put(‘ name ‘,9.);’; else put @3‘study_new=’ name ‘;’; if eof thenput‘run;’; run;
%include stud; filename stud;
Le code sauvegardé dans le fichier TMP_STUD.SAS se présente donc ainsi, vu que la variable STUDY est de type caractère.
data study_new; set excel_import;
study_new=STUDY ; run;
L’instruction %INCLUDE permet l’exécution de ce code.
L’octet (byte en anglais) est une unité de mesure informatique utilisée en SAS pour définir la longueur des variables. Il permet de stocker 1 caractère parmi une liste de 256. Une des listes de caractères les plus répandue est la table des ASCII (American Standard Code for Information Interchange). SAS dispose de deux fonctions RANK et BYTE pour passer d’un nombre à un de ces caractères et inversement. Ces notions sont à découvrir ou redécouvrir sous la forme de 9 points.
1. Des notions mathématiques mises à la sauce informatique
Deux valeurs possibles avec les booléens : Les booléens (boolean) sont des valeurs égales à 0 ou à 1. C’est une notation mathématique. On parle souvent de la logique des booléens. L’interprétation de ces valeurs est :
0 pour faux (false)
1 pour vrai (true)
En SAS, les syntaxes FIRST/LAST et END= du data step se servent de la logique des booléens.
Le bit est l’unité informatique de base : L’unité de mesure élémentaire en informatique, le bit (bit en anglais également) est basé sur le même principe. Le bit prend soit la valeur 0, soit la valeur 1.
L’octet est un groupement de 8 bits : Un octet (byte en anglais) est égal à la combinaison de 8 unités élémentaires, de 8 bits.
2. Le but du jeu
En informatique, le but du jeu est de n’utiliser que des valeurs 0/1 pour faire référence à des nombres entiers. Pour avoir un éventail de nombre entier assez large, il faut donc plusieurs bits.
Ensuite, pour chaque nombre entier une valeur peut être assignée. Par exemples, les nombres allant de 0 à 255 servent dans une table de référence pour les caractères, la table des ASCII.
3. Combien de valeurs différentes sont extraites avec x bits ?
Tout d’abord, les bits sont mis les uns à la suite des autres.
Avec 1 bit : le bit prend soit la valeur 0 soit la valeur 1.
Avec 2 bits : les valeurs de 2 bits s’arrangent de 4 manières différentes à savoir 00, 01, 10 ou 11.
Avec 3 bits : les valeurs de 3 bits peuvent se présenter de 8 manières possibles 000, 001, 010, 011, 100, 101, 110, 111.
Généralisation : Pour savoir combien d’arrangements de 0 et 1 sont possibles, le nombre 2 (nombre de valeurs possibles dans un bit) est multiplié autant de fois qu’il y a de bits, soit 2x. En termes mathématiques, on parle du nombre d’arrangements avec répétition. Il s’agit bien du calcul avec répétition car les valeurs 0 et/ou 1 peuvent apparaître plusieurs fois.
Ecrire un exposant sous SAS : Pour mettre une valeur en exposant sous SAS, on fait suivre la base de 2 étoiles et de l’exposant. Voici un exemple pour une variable nommée EXPOSANT.
En langage mathématique : exposant=28
Sous SAS : exposant=2**8;
4. Quelle position pour mon bit ?
On commence par regarder celui qui est le plus à droite et on lui assigne la position 0. Celui qui suit aura une position 1, etc.
Avec 1 bit : le bit est en position 0.
Avec 2 bits : le premier bit est en position 1, le second en position 0.
Avec 3 bits : le premier bit est en position 2, le second en position 1 et le dernier en position 0.
Etc.
5. Création d’une liste de valeurs
Maintenant que la position (x) de chaque bit est connue, on va additionner des valeurs 2x à chaque fois que le bit est égal à 1. Voici donc quelques exemples avec 1, 2 et 3 bits. D’un côté, on a l’arrangement des bites, de l’autre la valeur que l’on peut en extraire.
Avec 1 bit, les valeurs finales sont entre 0 et 1.
« 0 » : 0
« 1 » : 20 = 1
Avec 2 bits, les valeurs finales sont entre 0 et 3.
« 00 » : 0 + 0 = 0
« 01 » : 0 + 20 = 0 + 1 = 1
« 10 » : 21 + 0 = 2 + 0 = 2
« 11″ : 21 + 20 = 2 + 1 = 3
Avec 3 bits, les valeurs finales sont entre 0 et 7.
« 000 » : 0 + 0 + 0 = 0
« 001 » : 0 + 0 + 20 = 0 + 0 + 1 = 1
« 010 » : 0 + 21+ 0 = 0 + 2 + 0 = 2
« 011 » : 0 + 21+ 20 = 0 + 1+ 2 = 3
« 100 » : 22 + 0 + 0 = 4 + 0 + 0 = 4
« 101 » : 22 + 0 + 20 = 4 + 0 + 1 =5
« 110 » : 22 + 21 + 0 = 4 + 2 + 0 = 6
« 111″ : 22 + 21+ 20 = 4 + 2 + 1 = 7
Avec 8 bits (1 octet) les valeurs vont de 0 à 255. Comme indiqué précédemment ces nombres servent pour la table des ASCII.
6. La table des ASCII et les fonctions RANK/BYTE
La table des ASCII regroupe les caractères en trois groupes :
0-31 : les codes de contrôle (control code) comme « passage à la ligne »
32-127 : les caractères imprimables (printable characters)
128-255 : les caractères spéciaux (special characters) comme é, à, û…
Note pour les claviers étrangers : La liste des caractères spéciaux est pratique à l’étranger lorsqu’un clavier d’ordinateur ne dispose pas des accents. Ainsi pour obtenir la lettre « é », maintenez la touche « Alt » enfoncé et tapez le nombre 0233. Voici ceux que j’utilise le plus souvent :
0224 à
0226 â
0231 ç
0233 é
0234 ê
0235 è
0238 î
0244 ô
0249 ù
0251 û
Exemples d’applications : Dans le cadre des fonctions SAS, je vais me concentrer sur les valeurs 32 à 255 car ce sont les valeurs que j’ai rencontré dans des data sets SAS. J’ai aussi eu besoin de vérifier qu’une macro pouvait toujours fonctionner quand elle rencontrait ces caractères dans un data set. Pour se faire, j’ai eu besoin de créer un data set les contenant.
7. Convertir un nombre en caractère (la fonction BYTE)
Dans cet exemple, la fonction BYTE génère toutes les valeurs ASCII imprimables et les sauvegarde dans une variable ASCII. Pour ce faire, une boucle est construite avec les instructions DO et END. C’est l’occasion d’introduire rapidement sous forme d’exemple la notion de boucle.
data one (drop=i); do i=32to127; *do i=128 to 255; ascii=byte(i); output; end; run;
La boucle est définie par variable i allant de 32 à 128 (et non 127) mais l’action est conduite seulement pour les valeurs 32 à 127. Les valeurs intermédiaires sont distantes d’une valeur 1 car l’incrémentation par défaut est 1. Pour changer cette valeur par défaut et disons prendre une valeur sur deux, on ajoute BY 2 dans l’instruction DO.
A chaque fin de boucle i est incrémenté par 1. Quand i=127, la valeur est calculée une dernière fois. Puis i est incrémenté par 1. Avec i=128, la condition n’est plus remplie. Le contenu de la boucle est ignoré. SAS s’intéresse à l’étape suivante dans le data step. Ici l’étape suivante est la suppression de la variable i définissant la boucle.
A chaque nouvelle valeur de la variable i, la variable ASCII est recalculée. Puis le record est ajouté dans le data set ONE grâce à l’instruction OUTPUT.
8. Convertir un caractère ASCII en nombre (la fonction RANK)
Dans cet exemple, la fonction RANK retourne la valeur numérique de la table ASCII pour la lettre « é ». Cette valeur est sauvegardée dans la variable VAL_NUM.
data two;
val_num=rank(‘é’); run;
9. Les multiples des octets dans le commerce
Dans le monde des disques durs…, et taille de fichiers…., vous entendez couramment parler de :
Kilooctet ou Ko (Kilo Byte KB en anglais),
Megaoctet ou Mo (Mega Byte MB),
Gigaoctet ou Go (Giga Byte GB),
Teraoctet ou To (Tera Byte TB).
A l’avenir, on entendre peut-être même parle de :
Petaoctet ou Po (Peta Byte PB),
Exaoctet ou Eo (Exa Byte EB),
Zebioctet ou Zo (Zebi Byte ZB),
Yobioctet ou Yo (Yobi Byte YB).
La Commission Electrotechnique International (International Electrotechnique Commission IEC) a développé un standard se basant sur des multiples de 10 de l’octet. Cependant, l’ancien standard peut encore être rencontré.
Nouveau standard : un Kilooctet est 1 000 octets (103). Un Megaoctet est 1 000 000 (106).
Ancien standard : un Kilooctet représente 1 024 octets (210). Pour le Megaoctet, on passe à 1 048 576 (220).
En résumé, en achetant un disque dur de 500 Go, le produit est plus intéressant s’il réfère à l’ancien standard car il aura une plus grande capacité. Par contre, si on a un fichier de 5 Mo à envoyer, il représente moins de volume si on parle avec le nouveau standard.
sasreference.com est un blog
sur le langage de programmation SAS que j'ai écris à mes débuts en SAS en 2006 dont l'objectif de partager les connaissances techniques de base auprès des utilisateurs francophones.
Aujourd'hui, je poursuis la création de contenus via ma société xxformat GmbH. Suivez-moi sur Linkedin.
"Avant d'entrer en Master 2 ESA, j'ai voulu acquérir une expérience professionnelle en SAS. Suite à la publication de mon CV sur www.sasreference.fr, j'ai obtenu une proposition de stage pour les mois d'été." Mélanie Bourgouin.
"Un mot pour te remercier de ton blog qui est vraiment très bien fait et très utile pour les personnes qui travaillent sur SAS. J’y apprends moi-même beaucoup de choses." Yann, 30 ans, Paris, Président de l'AESV.
"Lectrice régulière de votre blog, et utilisatrice de SAS au quotidien, vous m'avez beaucoup appris et pour cela je vous en remercie!" Emmanuelle, étudiante de 3ème année à l'ENSAI