Posts Tagged ‘byte’

h1

Un texte de 32 767 caractères passé au crible

septembre 1, 2008

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.

data test_ds;
   infile ‘C:/sasref/lgth_max.txt’;
   length test_new $ 32767;
   input test_new $;
run;

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 contents data=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.

ods listing close;
ods rtf file=‘C:/sasref/lgth_max.rtf’;
proc print data=test_ds;
run;
ods rtf close;
ods listing;

Pours les curieux : Changez la longueur pour 32 768 et expérimentez en direct les limites de SAS.

h1

9 points autour de la notion d’octet

juillet 28, 2008

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=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.

h1

Faire des petits avec l’instruction OUTPUT

mars 1, 2008

bouchons_fr.jpg 

Imaginez devoir créer plusieurs fois le même tableau avec des fréquences, des tests statistiques, etc. Pourquoi plusieurs fois ? Parce que chaque tableau inclus une population différente.

1. Une observation par tableau

Dans le cas le plus simple, chaque observation n’apparaît que dans un seul des tableaux à produire. Une variable identifie le tableau auquel l’observation est allouée et l’instruction BY utilise cette variable avec la procédure report ou autre.

Voici un exemple où les données sont publiées par pays dans des tableaux distincts. L’utilisation d’une valeur numérique pour le pays est optionnelle mais ajoute de la flexibilité pour trier les données.

proc format;
value cntry
1=’Chine’
2=’Malaisie’;
run;

proc report data=lab;
by cntry;
columns test cnt;

format cntry cntry.;

run;

2. Plusieurs tableaux pour une observation

Exemple : maintenant voici deux exemples des essais cliniques pour lesquels une observation peut servir à plusieurs tableaux.

  • Construire un tableau pour la population ‘per protocol’, un pour ‘intent-to-treat’ et un pour ‘safety’ : un patient valide par protocole est aussi pour l’analyse de sûreté mais tous les patients valides pour la sûreté ne répondent pas forcément aux critères du protocole.
  • créer un tableau par zone géographique : un tableau pour tous les pays couverts par l’étude clinique, un tableau par pays et un par centre dans un pays donné.

Dans ces deux cas, une observation peut être utilisée par plusieurs tableaux. La méthode précédente n’est plus suffisante. Voici la solution que je vous propose :

  • 1er tableau : extraire les observations correspondant au premier tableau en utilisant une condition listant le critère de sélection si besoin.
  • rendre ces observations uniques en ajoutant une nouvelle variable avec un numéro unique
  • sauvegarder ces observations dans un jeu de données
  • 2ème tableau : extraire les observations pour le second tableau
  • donner un numéro différent à ces observations
  • ajouter ces observations à celles précédemment sélectionnées
  • 3ème tableau : etc.

Dans l’exemple qui suit, quatre tableaux différents sont à produits. On intercalera le code suivant entre les procédures format et report mentionnées précédemment.

data lab;
set lab;
grp=1;
output;
if cntry=’CN’ then
do;
grp=2;
output;
end;
else if cntry=’MY’ then
do;
grp=3;
output;
end;
if cntr=1 and cntry=’CN’ then
do;
grp=4;
output;
end;
run;

3. Créer plusieurs jeux de données

L’instruction OUTPUT dirige, par défaut, les données vers le jeu de données nommé dans l’instruction DATA. Parfois, il faut créer plusieurs data sets à partir à partir d’un seul jeu de données. Par exemple, on créera un data set contenant les patients inclus dans l’étude et un autre ceux exclus. Pour cela, il suffit de nommer les nouveaux jeux de données dans l’instruction DATA et de rappeler leur nom dans chaque instruction OUTPUT.

data incl excl;
set pat_lst;
if missing (randomno) then output excl;
else output incl;
run;

4. Créer une variable numérique avec des valeurs continues

En combinaison avec une boucle, l’instruction OUTPUT permet de générer des nombres. Par exemple, j’ai eu besoin de tester une macro via un data set listant toutes les valeurs ASCII imprimables. Ces valeurs ont un numéro allant de 32 à 126. La fonction BYTE retrouve la valeur ASCII avec ces numéros.

data ascii (drop=i);
do i=31 to 126;
ascii=byte(i);
output;
end;
run;

Autres lectures : vous pouvez étendre votre lecture sur l’instruction DO et DELETE. L’instruction DO dispose d’un mot-clé BY. L’instruction DELETE est, quant à elle, l’inverse de l’OUTPUT.