Archive for the ‘Fonctions’ Category

Protégé : Plusieurs formats pour une variable numériques – passer à une variable caractère avec la fonction PUTN
octobre 14, 2010
Ajouter une date dans un nom de fichier Excel, Word…
mars 12, 2009Sous 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
- Mes premiers pas avec ODS TAGSETS.EXCELXP (Partie 1/3)
- Mes premiers pas avec ODS TAGSETS.EXCELXP (Partie 2/3)
- Mes premiers pas avec ODS TAGSETS.EXCELXP (Parite 3/3)
Les fonctions
Les formats :
Les macros fonctions
- Additionner deux macros variables : la fonction %EVAL (usage de %SYSFUNC)
- Combien d’observations dans mon data set (usage de %SYSFUNC)

Enlever certains caractères spéciaux avec la fonction TRANSLATE
février 23, 2009Cet article est réécrit. Découvrez le sur : programmeur-pro.com
Les 256 caractères ASCII (American Standard Code for Information Interchange) comprennent :
- les lettres de l’alphabet,
- les chiffres
- des lettres accentuées propres à certains langues comme le E accent aigü
- des caractères non imprimables comme un tabulation, un retour à la ligne ou un espace.
Ils peuvent notamment arriver dans une table suite à l’importation d’un fichier Excel où ils sont présents. En général, la plupart de ces caractères spéciaxu ne sont pas désirés.
Quels sont ces caractères et comment les éliminer ?
1. Quels sont les 34 caractères non imprimables ?
Les caractères ASCII sont numérotés :
- de 0 à 256 (valeur décimale)
- de 00 à FF (valeur hexadécimal)
- Unicode
Cet article est réécrit. Découvrez le sur : programmeur-pro.com
Les 33 premiers caractères (0 à 32) et le caractère 127 sont forment les caractères non imprimables.
DEC HEX Description
0 00 NUL Null
1 01 STX Start of Header
2 02 SOT Start of Text
3 03 ETX End of Text
4 04 EOT End of Transmission
5 05 ENQ Enquiry
6 06 ACK Acknowledge
7 07 BEL Bell
8 08 BS BackSpace
9 09 HT Horizontal Tabulation
10 0A LF Line Feed
11 0B VT Vertical Tabulation
12 0C FF Form Feed
13 0D CR Carriage Return
14 0E SO Shift Out
15 0F SI Shift In
16 10 DLE Data Link Escape
17 11 DC1 Device Control 1 (XON)
18 12 DC2 Device Control 2
19 13 DC3 Device Control 3 (XOFF)
20 14 DC4 Device Control 4
21 15 NAK Negative acknowledge
22 16 SYN Synchronous Idle
23 17 ETB End of Transmission Block
24 18 CAN Cancel
25 19 EM End of Medium
26 1A SUB Substitute
27 1B ESC Escape
28 1C FS File Separator
29 1D GS Group Separator
30 1E RS Record Separator
31 1F US Unit Separator
32 20 [Space] Space
127 7F DEL Delete
Source : ascii-table.com
Cet article est réécrit. Découvrez le sur : programmeur-pro.com
2. Un exemple, le symbole « Line Feed »
L’image ci-dessous présent ene feuille Excel. La cellule A1 contient un passage à la ligne. Celui-ci indique la présence du caractère spéciale 0A (valeur hexadécimale).
Après la création d’une table SAS à partir d’un PROC IMPORT, cela donne un petit carré qui ne s’imprimera pas.
2. Comment éliminer des caractères spéciaux?
En fait, deux choix se présentent :
- soit vous éliminez les caractères spéciaux,
- soit vous les remplacez par des blancs
Dans les deux cas, la fonction TRANSLATE peut servir.
Créer le data set pour l’exemple :
data sasref;
f1=cat('Partie1','0A'x,'Partie2');
run;
Enlever le caractères spécial spécial grâce à la fonction TRANSLATE : la fonction TRANSLATE est composée de trois paramètres : le texte d’origine, les nouveaux caractères et les caractères à remplacer.
data sasref;
set sasref;
f2=translate(f1,' ','0A'x);
run;
Le résultat : J’ai choisi de créer une nouvelle variable F2 afin d’afficher simultanément le texte avant et le texte après.
La différence entre les fonctions TRANSLATE et TRANWRD :
- A la différence de la fonction TRANWRD, chacune des lettres est remplacée et non des mots.
- De plus, ici les caractères à remplacer sont cités en dernier (3ème paramètre de la fonction TRANSLATE). Tandis que TRANWRD commence par eux (2ème paramètre de laf onction TRANWRD).
Remplacer plus d’un caractère : vous pouvez lister autant de caractères hexadécimaux dans le troisième paramètre de la fonction TRANSLATE.
Ici, SAS remplacera les dix premiers caractères ASCII numérotés 00, 01, 02,…09, 0A, s’ils existent, pas un espace.
data sasref;
set sasref;
f2=translate(f1,' ','000102030405060708090A'x);
run;
Cet article est réécrit. Découvrez le sur : programmeur-pro.com
Lectures complémentaires :
- 9 points autour de la notion d’octet : la section 6 traite des ASCII
- Choisir ses couleurs sous SAS
- La concaténation : 4 fonctions SAS 9
Cet article est réécrit. Découvrez le sur : programmeur-pro.com
Annexe :
Reproduire le fichier Excel : Dans Word, tapez le texte en ajoutant un passage à la ligne. Copiez ensuite ce texte dans au niveau de la base fonction (fx).
Importer le fichier Excel dans SAS :
proc import file='C:/sasref/hexa.xls'
out=sasref
replace;
getnames=no;
run;
Cet article est réécrit. Découvrez le sur : programmeur-pro.com

Deux réponses possibles avec la fonction IFN
janvier 19, 2009Les fonctions IFN et IFC existent depuis la version 9.1 de SAS. Elles permettent de retourner une valeur si une condition est remplie et une autre si ce n’est pas le cas. Je vous propose d’illustrer la fonction IFN en combinaison avec la fonction LAG.
1. La différence entre les fonctions IFN et IFC
La fonction IFN retourne une valeur numérique alors que la fonction IFC retourne une valeur caractère.
2. Trois paramètres obligatoires pour ces fonctions et un optionnel
Dans un premier temps, il s’agit de définir une condition.
- Paramètre 1 : définir la condition
Dans un second temps, on assigne chacune des valeurs prises par la nouvelle variable selon que
- Paramètre 2 : valeur si la condition est remplit,
- Paramètre 3 : valeur si la condition n’est pas remplit
- Paramètre 4 : valeur si la condition donne une valeur manquante (optionnel).
3. L’exemple
Dans cet exemple, on a trois variables : PATIENT_ID et CNTRY_ID sont les variables clés. STRT_DT est la date de début d’un effet secondaire.
data adverse_events; input patient_id cntry_id $ strt_dt; informat strt_dt date9.; datalines; 999 DE 03MAR2004 999 DE 04MAR2004 999 DE 06MAR2004 111 AU 12DEC2003 111 AU 15DEC2003 ; run;
On souhaite créer une nouvelle variable contenant la date précédente par patient.
patient_id cntry_id strt_dt prev_dt 999 DE 03MAR2004 . 999 DE 04MAR2004 03MAR2004 999 DE 06MAR2004 04MAR2004 111 AU 12DEC2003 . 111 AU 15DEC2003 12DEC2004
La solution classique serait d’utiliser un FIRST qui implique que les données soient triées au préalable par patient.
proc sort data=adverse_events; by patient_id cntry_id; run; data adverse_events; set adverse_events; by patient_id cntry_id; prev_dt=lag(strt_dt); first.cntry_id then prev_dt=.; run;
Mais maintenant qu’on a la fonction IFN, la démarche est plus rapide. Dans notre exemple, seuls les trois paramètres obligatoires de la fonction IFN sont utilisés.
data adverse_events; set adverse_events; prev_dt=ifn(patient_id=lag(patient_id) and cntry_id=lag(cntry_id), lag(strt_dt), .); run;
4. Liens
La fonction LAG

Scanner une chaîne de caractère et extraire le xème mot
septembre 12, 2008Scanner 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’ then output 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.

9 points autour de la notion d’octet
juillet 28, 2008L’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=32 to 127;
*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.

Mes valeurs sont t’elles proches de la moyenne ? (écart-type)
juin 17, 2008Pour résumer une série de mesures, il est courant de proposer la moyenne. Mais avoir une moyenne de 11 n’a pas le même sens selon que les valeurs soient dispersées entre 10 et 13, ou entre 0 et 20. Dans le premier cas, toutes les valeurs sont plus proches de la moyenne que dans le second cas. L’écart-type (ou standard deviation en anglais) reflète cette subtilité. Le statisticien aura pour rôle d’interpréter cette valeur. En comprenant le sens d’un écart-type, le programmeur trouvera un outil supplémentaire pour vérifier la cohérence de ses résultats.
1. Des variables continues
La moyenne et l’écart-type sont des outils s’appliquant uniquement aux données numériques, suivant un ordre donné où l’écart entre chacune des valeurs potentielles est toujours le même. On peut donc parler de valeurs continues au sens large du terme.
Ainsi, l’âge d’une personne est une donnée continue qu’elle soit arrondie en années, en mois, en jours, en heure. La moyenne et l’écart-type auront une précision similaire.
2. Définition l’écart-type d’une population
L’écart-type ayant pour but de chiffrer l’écart entre les valeurs et la moyenne. Il est donc logique de calculer la différence entre chaque valeur et la moyenne. Dans un premier temps, on a autant de différences que de valeurs. Dans un second temps, une valeur moyenne est extraite de ces différences.
1. Mettre au carré les différences : qui dit moyenne, dit somme des valeurs divisé par le nombre de valeur. Hors, la somme de valeurs positives et négatives s’annulent. Et dans notre cas, on a bien des valeurs inférieures et des valeurs supérieures à la moyenne. Dans le cas de l’écart-type, toutes les différences sont rendues positives en les multipliant par elles-mêmes (mises au carré).
C’est probablement pour des faciliter la résolution de calculs mathématiques que la mise au carré est préféré à la prise des valeurs absolu. Si vous avez une autre hypothèse, n’hésitez pas à en faire part.
2. Extraire la moyenne : on souhaite une moyenne. Donc la somme des différences (mises au carré) sont divisées par le nombre de différences. Si on s’arrête là, la statistique s’appelle la variance.
3. Exprimer la dispersion dans la même unité que la moyenne : A présent la somme des différences n’est plus dans la même unité que la moyenne. Pour parler dans la même unité, on prend la racine de l’ensemble du calcul.
3. Estimer l’écart-type d’une population à partir d’un échantillon
Contexte : il est fréquent de ne pas travailler sur la population qui nous intéresse mais sur un échantillon. Par exemple, si on mesure la pression artérielle systolique des patients d’une étude clinique pour savoir si la drogue a permis de la réduire, le statisticien n’est pas intéressé par la moyenne de ces patients mais bien celle de tous les personnes pouvant à l’avenir faire appel à cette drogue.
Le problème : De plus, les recherches statistiques ont permis de démontrer qu’en moyenne, la moyenne de tous les échantillons possibles est la même que celle de la population. Pour l’écart-type, c’est un peu moins simple, puisqu’il la moyenne des écarts-types de tous les échantillons n’est pas exactement égale à celle de la population.
La solution : Mais les chercheurs en statistique sont là ! Ils ont réussi à montrer qu’en enlevant 1 au nombre total de valeurs dans chacun des échantillons, on pouvait retrouver l’écart-type de la population (cf. des cours d’inférence qui semble si théorique au prime abord mais qui permettent d’accéder à l’arrière de la scène).
Vocabulaire : Et pour enrichir votre vocabulaire et surtout comprendre ces spécialistes sachez que si l’écart-type sera appelé un estimateur biaisé si le 1 n’est pas enlevé.
L’écart-type le plus utilisé est donc le second, celui où on divise les différences non pas par le nombre de différences mais le nombre de différences moins 1.
4. Comprendre la différence entre l’écart-type et l’erreur-type
Pour ceux qui auront une formation à composante statistique, vous pourrez être amené à expliquer en entretien ou à vos collègues la différence entre l’écart-type (standard deviation) et l’erreur-type (standard error).
La première différence, c’est que l’écart-type s’applique à des données, alors que l’erreur-type s’applique à la statistique de la moyenne.
A chaque fois, qu’un échantillon est pris, sa moyenne va servir à estimer la moyenne de la population. Bien-sûr, toutes les moyennes des échantillons ne sont pas identiques. Il existe une variabilité. Certains sont plus proches de la réalité que d’autre. Cette variabilité des résultats entre les échantillons est donnée par l’erreur-type. Ainsi un intervalle à l’intérieur duquel la moyenne de la population se tient pourra être estimé.
5. En langage mathématique, l’écart-type donne quoi ?
Pour désigner nos valeurs, le mathématicien utilise la lettre X.
- Xi représente la ième valeur de l’échantillon. Si on a 15 valeurs alors i prend les valeurs de 1 à 15 ou plus généralement les valeurs de 1 à n.
- La moyenne de ces Xi est symbolisée par un X avec une barre au dessus.
Pour calculer l’écart-type, on a parlé de trois étapes :
- sum(Xi-Xbar)2 Tout d’abord la différence entre chaque Xi et la moyenne X barre est calculée. Elles sont mises au carré. Puis, la somme de ces valeurs en est faite. On en profite pour préciser que les valeurs de i vont de 1 à n.
- sum(Xi-Xbar)2 / (n-1) Après, il s’agit de calculer la moyenne de ces valeurs
- racine(sum(Xi-Xbar)2 / (n-1)) Enfin, la statistique est convertie en une unité comparable à celle de la moyenne via la racine carré.
6. Et en langage SAS, comment trouver la valeur d’un écart-type ?
Dans tous les cas suivant, le dénominateur est n-1.
6.1 Fonction STD : La fonction STD (standard deviation) retourne la valeur de l’écart-type.
proc sql;
select std(age) as std_age
from sashelp.class;
quit;
6.2 Calcul manuel : dans un premier temps, la différence avec l’âge moyen est calculée pour chaque record. Chaque différence est mise au carré. Dans un deuxième temps, la somme de ces différences est divisée par le nombre de records moins 1. Enfin, la racine carrée du tout est prise.
proc sql;
create table step1 as
select (age-mean(age))**2 as step1
from sashelp.class;
select sqrt(sum(step1)/(count(*)-1)) as step2_3
from step1;
quit;
6.3 Les procédures PROC MEANS et PROC SUMMARY : dans les exemples ci-dessous, j’ai volontairement choisi l’instruction ODS OUTPUT pour extraire les statistiques dans un data set.
proc means data=sashelp.class;
var age;
ods output Summary=proc_means;
run;
proc summary data=sashelp.class print;
var age;
ods output Summary=proc_summary;
run;
6.4 La procédure PROC UNIVARIATE : deux sorties fournies par la procédure UNIVARIATE sont indifféremment disponible.
proc univariate data=sashelp.class;
var age;
ods output Moments=proc_univ_opt1;
ods output BasicMeasures=proc_univ_opt2;
run;

Convertir une variable caractère en numérique et inversement
avril 21, 2008Cet article est maintenant réécrit. Vous le retrouvez sur www.programmeur-pro.com.
Passer d’une variable numérique à une variable caractère ou inversement est fréquent en langage de programmation SAS. Les fonctions INPUT et PUT permettent de changer ainsi le type de la variable. Dans un premier temps, je vous propose deux exemples pour illustrer les deux situations. Dans un second temps, on verra deux emplois supplémentaires de la fonction PUT : ajouter des zéros avant et après le nombre, et passer d’une valeur caractère à une autre valeur caractère.
Exemples d’application : dans la vie courante, il est fréquent de créer une variable texte à partir de plusieurs autres. Dans le lot, il y a souvent une variable numérique. Celle-ci doit être convertie en texte avant la concaténation. A l’inverse, on peut vouloir extraire le chiffre d’une chaîne de caractère et le sauvegarder dans une variable numérique.
Note : Dans un data step, on est obligé de créer de donner un nom différent à la variable d’origine et à la nouvelle variable. Il est alors courant de renommer au préalable la variable d’origine pour pouvoir utiliser son nom pour la nouvelle variable. Ensuite, la variable d’origine est supprimée. Dans une procédure SQL, le même nom peut être utilisé.
1. Du caractère au numérique et inversement
La fonction INPUT est composée de deux paramètres : la variable texte ou directement la chaîne de caractère d’un côté, l’informat de l’autre.
Du caractère au numérique : ici, on indique à la machine qu’il faut lire la variable d’origine comme une variable texte pouvant atteindre une longueur de 16 caractères. Pour cela on utilise l’informat $16. On peut aussi choisir un informat $CHAR. : ici $CHAR16. (SAS Online Doc. : INPUT Function, Informats by Category)
data char_to_num;
x_char = ‘123456789.123456’;
x_num = input(x_char,$16.);
*x_num = 123456789.123456;
run;
Note : Pensez à ajouter un format sur la variable numérique si vous ne la lisez pas intégralement dans votre output.
Du numérique au caractère : dans l’exemple ci-dessous, on indique que la valeur à créer sera numérique avec 16 chiffres/point dont 6 après la virgule. C’est l’information donnée par le format numérique 16.6. Bien sûr, on peut avoir la longueur nombre à convertir peut-être plus petit sans risquer d’affecter la valeur. Une autre possibilité est d’utiliser le format BEST16. Si aucun nombre n’est précisé (BEST.) cela revient à BEST8. SAS cherche alors la meilleure réponse possible permettant d’entrer 8 chiffres/point. Les décimales pourront être tronquées s’il n’y a pas assez de place, voir les entiers.
data num_to_char;
y_num = 123456789.123456;
y_char = put(y_num,16.6);
*y_char = ‘123456789.123456’;
run;
2. Les plus de la fonction PUT
Ajouter des zéros aux extrémités du nouveau texte : le format z. permet de remplacer les espaces vides par des zéros. Dans l’exemple ci-dessous, la nouvelle variable aura une longueur de 8 caractères. Les deux derniers seront les chiffres après la virgule. Comme il n’y en a qu’un seul dans la variable d’origine, un zéro sera ajouté à la fin. Il reste deux espaces en début à remplir avec des zéros.
data num_char_zero;
z_num = 123.1;
z_char = put(z_num,z8.2);
*z_char = ‘00123.10’;
run;
Passer d’une valeur caractère à une autre : la valeur caractère d’origine peut aussi être du texte et non des chiffres. Dans cette situation, la nouvelle variable prend la valeur d’un format caractère souvent défini par le programmeur.
proc format;
value $cntry
FR = ‘France’
LU = ‘Luxembourg’
CH = ‘Suisse’;
run;
data char_to_char;
a1_char=’LU’;
a2_char=put(a1_char,$cntry.);
*a2_char=’Luxembourg’;
run;

2 syntaxes pour calculer un âge
avril 9, 2008Quel âge à mon patient au début de l’étude ? Et mon client, quel âge a t-il lors de la signature de son contrat x ? Ces questions simples a priori peuvent vite devenir un casse-tête avec SAS. Je vous propose deux approches qui vous permettront d’aborder succinctement plusieurs fonctions. Les fonctions les plus facile à comprendre MONTH, DAY, YEAR, INT/FLOOR sont traitées sous forme de notes. Les fonctions de base pour le calcul de l’âge YRDIF et INTCK sont introduites dans des sections distinctes. On ne parlera pas ici de la manière de créer une date SAS.
Note : les fonctions YEAR, MONTH et DAY permettent de retrouver respectivement l’année, le mois et le jour d’une date SAS. Elles n’ont donc que la date comme paramètre.
Note : la fonction INT (pour le mot anglais « integer ») retourne la partie entière d’un nombre. La fonction FLOOR retourne l’entier inférieur. En rappel, « floor » signifie le sol en anglais. Dans le cas d’entier positif, les fonctions INT et FLOOR donnent la même valeur. Cela s’applique donc à l’âge.
Présentation du jeu de donné utilisé comme exemple : pour illustrer ce calcul, je vous propose en fin d’article un data set avec :
- une variable pour la date de début (strt_dt),
- une autre pour la date de fin (end_dt).
1. La fonction YRDIF : la fonction YRDIF contient trois paramètres : la date de début, la date de fin et le mode de définition des mois et années. Dans notre cas, on choisira des mois et années comme sur le calendrier et non des mois de 30 jours ou des années de 360 jours. Le troisième paramètre aura donc la valeur ‘ACT/ACT’ ou son alias ‘ACTUAL’.
yrdiff_val = yrdif(strt_dt,end_dt,‘ACTUAL’);
La valeur retournée est un nombre avec des virgules. Or il nous faut un nombre entier. Pour ne retirer que la partie entière, on ajoute la fonction INT.
int_yrdiff_val = int(yrdif(strt_dt,end_dt,‘ACTUAL’));
Maintenant, dans le cas particulier du jour anniversaire, on se rend compte que selon qu’il s’agit d’une année bissextile ou non, on a une valeur supérieure ou inférieure à un. On ajoute donc une condition pour ce cas particulier. Si les mois et jours sont identiques, on fait la soustraction entre l’année de fin et celle de début.
if month(strt_dt) = month(end_dt) and
day(strt_dt) = day(end_dt)
then age_m1 = year(end_dt)-year(strt_dt);
else age_m1 = int(yrdif(strt_dt,end_dt,‘ACTUAL’));
2. Une seule instruction : calculer la date en une seule instruction, c’est possible. Le calcul a été répertorié sur le forum SAS-L. Je vous propose de la détailler ici.
2.1 La fonction INTCK : la fonction INTCK avec pour premier paramètre ‘month’ a pour valeur minimale 0. On rencontre ce cas lorsque les mois et année des deux dates coïncident. Pour le même mois un an après, SAS retournera une valeur de 12.
cnt_mois = intck(‘month’,strt_dt,end_dt);
2.2 Comparer les jours : si le jour de début est supérieur au jour de fin, le mois entier ne s’est pas écoulé. On enlève donc un mois au calcul précédent. Le résultat de la parenthèse (day(strt_dt) > day(end_dt) est soit 0, soit 1.
comp_jr = day(strt_dt) > day(end_dt);
2.3 S’exprimer en années : comme on veut le résultat en années et non en mois, le tout est divisé par 12.
2.4 Avoir un nombre entier : l’individu prenant un an de plus seulement quand l’âge est révolu, seule la partie entière nous intéresse. Une fonction INT ou FLOOR fera l’affaire.
age_m2 = int((intck(‘month’,strt_dt,end_dt)-(day(strt_dt)>day(end_dt)))/12);
3. Illustration avec des données : En plus des variables strt_dt (start date) et end_dt (end date), les observations sous regroupées en 4 catégories (variable flag).
- Les dates anniversaires,
- La veille et le lendemain de ces dates anniversaires.
- Des dates de début et de fin identiques.
Des années bissextiles et des années de 365 jours sont incluses.
data strt_end;
length flag $3;
format strt_dt end_dt date9.;
informat strt_dt end_dt date9.;
input strt_dt end_dt flag $;
datalines;
02APR1979 02APR1980 =1
02APR1980 02APR1981 =1
02APR1981 02APR1982 =1
02APR1979 01APR1980 <1
02APR1980 01APR1981 <1
02APR1981 01APR1982 <1
02APR1979 03APR1980 >1
02APR1980 03APR1981 >1
02APR1981 03APR1982 >1
02APR1979 02APR1979 =0
02APR1980 02APR1980 =0
02APR1981 02APR1981 =0
;
run;
Dans cette sortie, on trouve les dates de début et de fin. Puis, on distingue d’un côté les deux variables illustrant la méthode 1 et ensuite celles de la méthode 2.
__METHODE 1__ ____METHODE 2____
yrdiff_ age_ cnt_ comp par_ age
strt_dt end_dt val m1 mois _jr annee m2
02APR1979 02APR1980 1.00205 1 12 0 1.00000 1
02APR1980 02APR1981 0.99795 1 12 0 1.00000 1
02APR1981 02APR1982 1.00000 1 12 0 1.00000 1
02APR1979 01APR1980 0.99932 0 12 1 0.91667 0
02APR1980 01APR1981 0.99521 0 12 1 0.91667 0
02APR1981 01APR1982 0.99726 0 12 1 0.91667 0
02APR1979 03APR1980 1.00478 1 12 0 1.00000 1
02APR1980 03APR1981 1.00069 1 12 0 1.00000 1
02APR1981 03APR1982 1.00274 1 12 0 1.00000 1
02APR1979 02APR1979 0.00000 0 0 0 0.00000 0
02APR1980 02APR1980 0.00000 0 0 0 0.00000 0
02APR1981 02APR1981 0.00000 0 0 0 0.00000 0

Retrouver la valeur suivante avec LAG ou un MERGE
mars 5, 2008
Dans un précédent article, la fonction LAG a été présentée. Il s’agissait alors de créer une nouvelle variable contenant la valeur précédente d’une variable existante. Pour récupérer la valeur suivante cette fois, je vous propose deux méthodes : utiliser la fonction LAG avec un tri décroissant ou faire un MERGE.
1. Trier par ordre décroissant et utiliser la fonction LAG : pour retrouver l’information suivante plutôt que l’information précédente, il vous suffit de trier les observations par ordre décroissant au préalable. Dans notre exemple précédent, (1, 2, 3, 4, 5) devient (2, 3, 4, 5, .). Afin de retrouver l’ordre d’origine, vous aurez besoin d’un second tri après. Cette fois-ci, c’est la dernière observation par patient qui sera manquante puisqu’il n’y a pas d’observation après pour un patient donné. En SAS, cela veut dire qu’il faudra utiliser LAST après le tri final ou FIRST avant le tri final.
proc sort data=test;
by patient descending dt;
run;
data next_dt;
set test;
by patient;
next_dt=lag(dt);
if first.patient then next_dt=.;
run;
proc sort data=next_dt;
by patient dt;
run;
2. Extraire la valeur suivante avec un MERGE : en extrayant la variable date sans sa première observation dans un jeu de donnée, on obtient la liste des valeurs suivantes. Il suffit ensuite d’ajouter ces valeurs au jeu de données d’origine pour avoir la 2ème date comme valeur suivante pour la première observation, etc. Un MERGE sans instruction BY est suffisant. Comme avant, on actualise la dernière observation par BY variable via LAST.
proc sort data=test;
by patient dt;
run;
data next_dt;
merge test
test (firstobs=2 rename=(dt=next_dt));
run;
data next_dt;
set next_dt;
by patient;
if last.patient then next_dt=.;
run;

Retrouver l’information précédente avec la fonction LAG
mars 4, 2008Lorsqu’un test médical est conduit plusieurs fois sur un patient, les résultats pourront être sauvegardés dans une variable par ordre chronologique. Pour étudier le changement entre deux examens, on peut créer une nouvelle variable contenant l’information précédente. Ceci est un exemple d’application de la fonction LAG qui récupère la valeur de l’observation précédente.
Ici je vous propose d’aborder cette fonction. Les exemples vont utiliser un jeu de donnée, nommé ‘test’, qui contient une variable identifiant chaque ‘patient’ et une variable date ‘dt’. On peut donc avoir plusieurs dates par patient. L’objectif est de créer une nouvelle variable contenant la date précédente ou suivante.
1. La fonction LAG retrouve l’observation précédente : si une variable x à cinq valeurs (1, 2, 3, 4, 5) et qu’une nouvelle variable y contenant le LAG de x est créée, cette nouvelle variable aura (., 1, 2, 3, 4) comme valeurs. Ceci veut aussi dire qu’il y aura autant d’observations y que d’observations x. Les données devront être triées au préalable.
2. Obtenir la valeur précédente par sous groupe : la fonction LAG est indépendante d’une BY variable (ex : par patient). La première observation d’un patient devra pourtant être toujours manquante, puisqu’il n’y a pas de valeur avant pour ce patient. Pour que cette observation ne vienne pas du patient précédent, on la remplace par une valeur manquante grâce à FIRST. Mais la condition sur cette première observation sera faite après le LAG et non avant.
proc sort;
data=test;
by patient dt;
run;
data next_dt;
set test;
by patient;
next_dt=lag(dt);
if first.patient then next_dt=.;
run;
3. Retrouver une information précédente mais pas la dernière3.1 Sauter plusieurs observations : la fonction LAG peut être agrémentée d’un nombre pour préciser l’écart avec l’observation actuelle. LAG(x) est équivalent de LAG1(x). Ainsi dans notre exemple précédant (1, 2, 3, 4, 5), LAG2(x) donne (., ., 1, 2, 3).
3.2 Par sous-groupe : pour trouver l’information par sous-groupe, il faut ajouter un compteur. Celui-ci permet de définir une condition pour remplacer les dernières observations de chaque patient par des valeurs manquantes.
data next_dt2 (drop=cnt);
set test;
by patient;
next_dt2=lag1(dt);
cnt+1;
if first.patient then cnt=1;
if cnt in (1,2) then next_dt2=.;
run;
En résumé, la fonction LAG ‘fait descendre’ de z steps les données. On peut récupérer l’observation précédente contigue ou une information plus lointaine.

Les 2 visages de la fonction SUBSTR
février 26, 2008Une nouvelle version de cet article est maintenant disponible sur programmeur-pro.com.
Une nouvelle version de cet article est maintenant disponible sur programmeur-pro.com.
Définir une nouvelle variable à partir de x caractères d’une autre variable. Substituer, dans une variable texte, les x caractères à partir du zème. Ces deux thématiques fortes différentes sont traitées avec la même fonction SUBSTR. Selon qu’elle soit placée à gauche ou à droite de l’égalité, la fonction répond à un besoin différent.
1. Créer une nouvelle variable à partir d’un sous-ensemble d’une autre : l’application la plus courante de la fonction SUBSTR consiste à conserver un sous-ensemble d’une chaîne de caractères, en se référant à sa position de départ et à sa longueur, pour définir une nouvelle variable.
Notation : la fonction est composée de trois paramètres
-
le nom de la variable d’origine,
-
la position du premier caractère qui nous intéresse,
-
le nombre total de caractères à partir du point de départ (optionnel).
Exemple : dans l’exemple suivant, imaginez une variable TESTCASE. Les tests tc0101, tc0102 appartiennent au même groupe, tandis que tc0201 appartient à un groupe différent. Les deux premiers chiffres font référence au groupe. Pour sauvegarder ces chiffres dans une variable GRP, on utilise la fonction SUBSTR.
grp=substr(testcase,3,2);
Note : Si le nombre de caractères à retenir n’est pas précisé par un troisième paramètre, c’est tout le reste de la chaîne à partir de la position donnée en second paramètre qui est conservé.
grp=substr(testcase,3);
2. Remplacer une partie d’une chaîne de caractères : pour actualiser une variable dans un data step, la démarche sous SAS est fastidieuse. Dans un cas particulier, cependant, on peut l’éviter : changer un sous-ensemble d’une variable texte défini par sa position dans la chaîne et sa longueur.
Rappel, actualiser une variable dans un data step : dans un premier, la variable est renommée. Cette variable contient les valeurs d’origine, celle qui nous intéressent. On peut ainsi définir une nouvelle variable portant le nom d’origine puisque ce nom n’existe plus. Cette nouvelle variable prendra nos valeurs d’origine, plus les nouveautés voulues via une addition, une concaténation ou autre.
Exemple : on reprend l’exemple de la première section avec notre variable TESTCASE. La chaîne ‘tc’ commençant en position 1 et longues de 2 est remplacée par les caractères ‘AB’.
substr(testcase,1,2)=’AB’;
Notez que la valeur de substitution doit être de la même longueur. Si elle est plus grande, les caractères seront ignorés. Si elle est plus petite, des blancs remplaceront les espaces manquants. De plus, on ne peut substituer que parmi les caractères existants, blancs de début et fin de chaîne compris.

Fini le Moyen-Age pour compter les mots
février 20, 2008
Vous avez une variable composée d’un ou plusieurs mots pour chaque observation, le tout séparé par des espaces, des virgules ou autre. Et vous voulez savoir combien il y a de mots. Avec SAS 9, il est très rapide de trouver le nombre de mots. Avec SAS 8.2, il faut pallier à l’absence de la fonction COUNT. Dans les deux cas, l’idée est la même : on compte les délimiteurs et on ajoute 1.
Prenons le cas des espaces. Dans un premier temps, on enlève les blancs de début et de fin de chaîne. Puis on enlève les doublons entre les mots. Enfin on compte les espaces restants. Il faudra aussi tenir compte du fait qu’une observation puisse ne contenir aucune valeur.
Voici les données qui serviront d’exemple :
data ds_orig;
x=‘ AB CD GH ‘;
output;
x=‘ ‘;
output;
x=‘AB ‘;
output;
run;
1. Avec SAS 9, un calcul rapide : il faudra faire appel à:
-
la fonction STRIP pour les blancs aux extrémités,
-
la fonction COMPBL pour enlever les blancs doublons,
-
la fonction COUNT pour compter le nombre d’occurrence d’un caractère donné,
-
la fonction MISSING ou un simple = ‘ ‘ pour savoir si la chaîne est vide.
Voici un exemple avec des espaces pour délimiteur.
data sas9 ;
set ds_orig;
if x = ‘ ‘ then nb_mots = 0;
else nb_mots=count(compbl(strip(x)),‘ ‘) + 1;
run;
2. Avec SAS 8.2, il faut contourner l’absence de la fonction COUNT: il existe plusieurs options dont celle-ci utilisant une boucle DO WHILE:
-
Les fonctions TRIM et LEFT remplacent la fonction STRIP.
-
Les fonctions COMPLB et MISSING restent valide.
-
Une boucle remplacera la fonction COUNT.
On extrait le 1er mot de la chaîne, puis le 2nd, etc. via la fonction SCAN. Si la valeur trouvée est une valeur manquante, alors le nombre de mots est égal au nombre du boucles sans valeur manquante, c’est-à-dire le nombre de boucles actuel moins 1. Le compteur, ici nommé i, est réinitialisé pour arrêter la boucle DO WHILE.
data sas8_2;
set ds_orig;
if missing(x)then cnt_mots=0;
else
do;
z=compbl(trim(left(x)));
i=1;
do until (i=0);
if missing(scan(z,i,‘ ‘))then
do;
cnt_mots=i-1;i=->1;
end;
i=i+1;
end;
drop i z;
end;
run;

J’additionne des valeurs manquantes
février 16, 2008Une simple somme de deux nombres et vous obtenez un résultat différent de vos attentes. C’est possible avec SAS lorsque des valeurs manquantes (missing et special missing) sont incluses. Je vous propose de découvrir la différence entre les opérateurs mathématiques et les fonctions de calcul au travers de la fonction SUM.
Voici la règle : les fonctions de calcul SAS ignorent les valeurs manquantes. Ainsi avec la fonction SUM, la somme de 2 et d’une valeur manquante est 2, alors qu’il est valeur manquante avec l’opérateur + d’addition : 2 +. = .
A présent, voyons les trois notations de la fonction SUM.
1. Lister les valeurs comme autant de paramètres de la fonction SUM : les paramètres d’une fonction SAS se séparent par une virgule. Pour faire la somme de plusieurs valeurs, vous pourrez les lister les unes à la suite des autres dans les parenthèses de la fonction SUM en les séparant par une virgule :
newvar = sum(2,3,.);
Mais soyons honnête, vous aurez plus souvent l’occasion de faire référence aux valeurs par de l’intermédiaire de variables qu’en listant des données brutes :
newvar = sum(x,y,z);
2. Le mot-clé OF pour lister les valeurs à additionner sans virgule : pour lister sans virgule les données à additionner dans la fonction SUM, il faut absolument ajoutez le mot-clé OF :
newvar = sum (of 2 3 .) ;
newvar = sum(of test2 test3 test4);
3. Le mot-clé OF c’est aussi un moyen de lister de nombreuses variables au nom proche : dans l’exemple précédent, les variables portent des noms ayant une base commune et un nombre entier toujours incrémenté de 1. En définissant un intervalle listant les première et dernière variables séparées par un trait d’union, vous vous épargnerez un travail qui devient vite fastidieux avec un nombre de variables qui augmente.
newvar = sum(of test2-test4);
Cette notation n’est pas propre à la fonction SUM. Elle s’applique dans de nombreux contextes : une option KEEP, DROP, un ARRAY, etc.
Important : notez ici l’importance de ne pas oublier le mot-clé OF. Dans l’exemple précédent, SAS soustrairait la variable test4 à la variable test2 si le mot-clé OF n’apparaissait pas. La fonction SUM n’aurait alors qu’une valeur.
Autres lectures : les fonctions MIN et MAX et leur corollaires >< et <> fonctionnent sur le même principe que la fonction SUM et l’opérateur + lorsqu’ils traitent des valeurs manquantes.

Majuscule ou minuscule sous SAS
février 9, 2008Les mots majuscule et minuscule sont traduits en anglais par uppercase et lowercase. Lorsqu’un langage de programmation est sensible aux différences entre les deux, on dit qu’il est case-sensitive. Ce vocabulaire vous sera utile pour comprendre la suite de cet article.
1. SAS n’est pas sensible au changement entre majuscules et minuscules la plupart du temps : SAS ne fera pas la différence entre les textes tantôt écrits en majuscules, tantôt en minuscules dans de nombreux cas. Voici quelques exemples :
- les mots de syntaxe propre à SAS (data, proc, do, if, filename, etc.),
- le nom des bibliothèques (libname orig_data « c:/ »; data demo; set Orig_DATA.demo; run;),
- le nom des jeux de données SAS (data demo; set DEmo;run;),
- le nom des variables (age, Age, AGE).
Illustration : en consultant les métadonnées via les dictionnaires ou la procédure proc contents, on note que tous les noms des bibliothèques sont standardisées quelque soit la notation d’origine. Notez cependant le cas particulier des noms de variables qui continuent d’apparaître comme lors de la saisie initiale dans les métadonnées mais peuvent être référencées indifféremment de la case (if test=’ID’; if Test=’ID’;).
Conseil : la lecture des minuscules est plus facile. Je vous conseille de les privilégier pour écrire votre code. Vous réserverez ainsi les majuscules pour les cas particuliers, et pourrez ainsi les repérer plus facilement lors de la lecture de votre programme.
2. Les valeurs définies entre guillemets sont sensibles à la case : voici trois exemples de données sensibles aux majuscules :
- les données des variables caractères (cntry=’FR’;),
- le label des variables (label cntry=’Pays’;),
- le label des data sets (data demo (label=’Panel Démographie’);).
Ces trois chaînes de caractères sont définies entre guillemets. Donc ici cntry=’FR’ est différent de cntry=’Fr’.
3. Deux fonctions pour évitez des erreurs, UPCASE et LOWCASE : pour vérifiez les valeurs d’une variable quelque soit sa case, pensez à faire une comparaison sur les valeurs standardisées (tout majuscule ou tout minuscule), au risque de perdre, sinon, des observations. Pour cela vous avez les fonctions UPCASE() et LOWCASE().
4. Exemple d’utilisation des fonctions UPCASE et LOWCASE avec les dictionnaires : personnellement je fais beaucoup appel à ces fonctions pour récupérer une partie des informations des dictionnaires. Voici un exemple où toutes les données du dictionnaire TABLE faisant appel à la bibliothèque temporaire WORK sont récupérées :
proc sql ;
select *
from dictionary.tables
where upcase(libname)='WORK';
quit;
NOTE : La fonction PROPCASE met la première lettre de chaque mot en majuscule et le reste en minuscule. Pour les acronymes où les lettres sont séparées par un point, toutes les lettres sont mises en majuscule.
Plus de détails sur ces fonctions sont disponibles dans la documentation en ligne : UPCASE Function, LOWCASE Function et PROPCASE Function.