Archives pour novembre 2008

h1

Naviguer dans le blog : les 102 premiers articles

novembre 26, 2008

La liste des articles publiés sur ce blog consacré à SAS s’agrandit de semaine en semaine. Voici un récapitulatif des 102 premiers triés par thématique pour parfaire votre navigation.

Découvrir l’environnement de travail

Ces premiers articles invitent le lecteur à découvrir le monde de SAS, son environnement et quelques notions de base comme les LIBNAME.

1. C’est quoi la programmation sous SAS ?

2. Mes raccourcis clavier préférés

3. Et par magie mon jeu de données a disparu (LIBNAME)

4. Il était une fois la LOG

Annoter ses programmes

L’utilisation des commentaires est très importante en tout langage de programmation. SAS ne fait pas exception. Voici quelques pistes pour bien documenter votre travail.

5. 3 angles de vue sur les commentaires

6. 8 clés pour vos en-têtes

7. Structure un programme, un exemple en 5 étapes

Les options des data sets

Les options d’un data set sont toujours listées entre parenthèses. Elles suivent directement le nom du data set. Ces options peuvent être définites aussi bien dans une étape data que dans une procédure. Jusqu’à présent, les options RENAME, KEEP/DROP, OBS, FIRSTOBS ont été présentées. Dans le dernier article vous trouverez en prime des options propres à l’instruction PROC PRINT comme WIDTH=min ou NOBS.

8. Je garde ou je jette? les variables

9. Renommer une variable (RENAME)

10. 3 options pour un aperçu de vos données brutes (PROC PRINT)

Les attributs des variables

Les variables sont caractérisées par leur type (caractère/numérique), leur longueur, leur informat et leur format. On parle alors des attributs de la variable. Jusqu’à présent, la longueur (LENGTH) et les formats ont été les sujets principalement traités.

11. 9 points autour de la notion d’octet

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

13. 2 méthodes pour de nouveaux formats

14. Proc Format : 7 points forts de VALUE

15. Supprimer des formats

16. Quel format a la pole position? (FMTSEARCH)

17. Arrondir ses chiffres avant d’appliquer un format

18. Changer la séquence d’affichage des variables

La procédure SQL

La procédure SQL est comparée à l’étape data dans plusieurs articles. Chaque méthode a ces avantages et ces limites. Ici, l’article vous propose de découvrir la syntaxe de base de la procédure SQL.

19. 4 étapes de base pour créer un data set avec PROC SQL

Créer, manipuler et supprimer des jeux de données (SAS data sets)

Saisir les données manuellement, les lire d’un fichier .TXT pour créer un data set, ajouter des lignes d’observations, supprimer des doublons, trier les données, les faire pivoter, supprimer un data set sont autant de manipulation courante dans la vie du programmeur SAS.

20. Créer un data set à partir de données brutes (Line input)

21. Lire des données d’un fichier .TXT sans perdre d’information (les options d’INFILE)

22. Faire des petits avec l’instruction OUTPUT

23. Identifier et supprimer les doublons

24. Trier les données par ordre croissant et décroissant

25. Faire pivoter un data set (un 1er exemple de PROC TRANSPOSE)

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

27. Supprimer un data set SAS en 6 points (PROC DATASETS)

Grouper les data sets

Combiner les data sets est un travail très important. Une bonne maîtrise de ces techniques est indispensable pour programmer correctement.

28. Empiler des data sets

29. Insérer quelques nouvelles observations

30. La base de la jointure de deux data sets avec MERGE

31. Oh attention danger avec MERGE et IF

32. Savoir interpréter une note liée au MERGE

33. Produit cartésien : un notion pas si barbare !

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

La notion de compteur

Pour créer un compteur, il faut dans un premier temps se familiariser avec la notion de RETAIN. Après pour faire varier les données, il faut utiliser les notions de FIRST et LAST. Ces dernières ne fonctionne qu’avec des données triées listées dans une intruction BY. Les deux derniers articles vous donneront des exemples d’application d’un RETAIN.

35. Repérer les 1ers/derniers records (FIRST/LAST)

36. Jongler avec les records grâce aux compteurs

37. Combien de contrats ai-je au total ? (2/5) RETAIN

38. 2 suggestions pour grouper les valeurs d’une variable

Les conditions

QU’il s’agisse d’une étape data ou de la procédure SQL, les conditions représentent une notion incontournable de la programmation SAS. A vous de découvrir les différentes notations, leurs forces et leurs limites.

39. Penser conditionnel (1/3) : La base du IF

40. Penser conditionnel (2/3) : SELECT

41. Penser conditionnel (3/3) : CASE WHEN

Manipuler les observations caractères (Les fonctions caractères)

Au quotidien, le programmeur est amené à utiliser les fonctions caractères. Les articles qui suivent contiennent les fonctions que j’utilise le plus.

42. Majuscule ou minuscule sous SAS

43. 4 fonctions pour enlever les blancs !

44. La concaténation : 4 fonctions SAS 9

45. Les 2 visages de la fonction SUBSTR

46. Scanner une chaîne de caractère et extraire le xème mot

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

48. Afficher 7h30 du matin sous la forme 07:30

49. Quand compilation et exécution font la différence, un exemple

Les fonctions numériques

Parmi les fonctions numériques vu, on citera les fonctions SUM, LAG, YRDIFF, COUNT et les fonctions propres aux dates comme MDY et DHMS. Parmie celles restent à couvrir, il y a les fonctions INT, FLOOR, CEIL, ABS, ROUND, IFN, IFC.

50. J’additionne des valeurs manquantes

51. Retrouver l’information précédente avec la fonction LAG

52. Retrouver la valeur suivante avec LAG ou un MERGE

53. 2 syntaxes pour calculer un âge

54. Fini le Moyen-Age pour compter les mots

55. Créer une date SAS de 3 manières

Fonctions permettant de jouer avec le type de la variable

Les fonctions PUT et INPUT sont probablement les fonctions les plus populaires sous SAS. Il est en effet très courant de devoir changer le type d’une variable. Cela requiert au préalable une compréhension des formats et informats. La fonction MISSING est abordée dans l’article sur les fonctions numériques (Additionner des valeurs manquantes). On retiendra qu’elle s’applique indifféremment aux variables numériques et caractères.

56. Convertir une variable caractère en numérique et inversement

Reporting

La notion de PROC REPORT a été principalement couverte laissant à plus tard la notion de PROC TABULATE. Le reporting s’améliore sur SAS. Ce qui explique la présence des sujets sur PROC TEMPLATE, ODS RTF et ODS TAGSETS.EXCELXP.

57. 6 notions pour débuter avec PROC REPORT

58. 5 options courantes de PROC REPORT

59. 9 points pour personnaliser ses titres

60. Ajouter des indentations dans un tableau

61. Améliorer l’habillage de vos tableaux (débuter avec PROC TEMPLATE via PROC REPORT)

62. Structurer les sauts de page (ODS RTF)

63. Des marges personnalisées pour vos rapports RTF

64. Mes 1ers pas avec ODS TAGSETS.EXCELXP (1/3)

65. Mes 1ers pas avec ODS TAGSETS.EXCELXP (2/3)

66. Mes 1ers pas avec ODS TAGSETS.EXCELXP (3/3)

67. Passer d’un fichier de l’ODS TAGSET.EXCELXP à un data set SAS avec PROC IMPORT

Les graphiques

Les graphiques sont un sujet peu abordé jusqu’à présent pour deux raisons : il est très peu utilisé dans le secteur pharmaceutique et reste très compliqué sous SAS.

68. 3 propositions pour exporter un graphique

69. Choisir ses couleurs sous SAS

Le langage macro

Une des trois méthodes pour répréter une action avec quelques variantes sont les macros.

70. Le luxe des macros, B.A.BA de la syntaxe

71. 3 méthodes pour construire des macros variables sans macro

72. Un besoin ponctuel de variables macros

73. Répéter une action sur plusieurs variables avec le langage macro

74. Mon paramètre de macro est-il rempli ?

75. Combien d’observations dans mon data set ?

Ecrire du texte dans d’autres destinations et travailler avec les métadonnées

Comme alternative aux macros, on trouve le DATA _NULL_ utilisé en combinaison avec les instructions PUT et les dictionnaires. Voici donc quelques notions de base (PUT et dictionnaires) pour après découvrir la puissant de cet outil qui sert au quotidien.

76. Ecrire un texte avec l’instruction PUT

77. Envoyez un email via SAS

78. Les 2 dictionnaires SAS les plus utilisés: TABLES et COLUMNS
Faire des calculs sous SAS

Les logarithmes et l’écart-type sont des notions qui intéresseront principalement ceux qui travaillent en statistique. PROC MEANS, PROC FREQ et la fonction COUNT dans PROC SQL ont été les principaux sujets relevants de calculs.

79. Des souvenirs de lycée, les logarithmes

80. Mes valeurs sont t’elles proches de la moyenne ? (écart-type)

81. Diriger les sorties d’un PROC MEANS dans un dataset SAS

82. Un tableau à une dimension avec PROC FREQ et ODS OUTPUT

83. Combien de contrats ai-je au total ? (1/5) PROC SQL

84. Combien de contrats ai-je au total ? (3/5) PROC MEANS

85. Combien de contrats ai-je au total ? (4/5) PROC FREQ

86. Combien de contrats ai-je au total ? (5/5) PROC TABULATE

L’environnement UNIX

Alors que dans le milieu universitaire et les entreprises ayant peu de programmeurs SAS, il est courant d’utiliser SAS sous Windows, dans les entreprises de plus grande taille, l’environnement Unix est privilégié. A l’avenir, je vous présenterais quelques commandes que j’ai jusqu’à présent inséré dans mes programmes SAS.

87. Gérer vos dossiers via UNIX, 2 raisons

88. Quel chemin prendre sous Unix?

Se former

Souhaitant rendre accessible SAS au plus grand nombre, je souhaite par les articles de cette section vous donner le plus d’information possibles sur les alternatives à disposition pour se former. Je vais continuer à vous présenter des formations incluant SAS dans leur cursus.

89. Une licence SAS pour 160 euros

90. Mes 3 principales sources de documentation

91. 20h de formation SAS au CNAM de Paris

Vie professionnelle


92. Le monde du programmeur SAS en pharma

93. 6 conseils pour vos emails

94. Choisir ses outils de communication

95. 7 conseils pour collaborer avec un programmeur SAS

Recrutement

Ces deux dernières années m’ont fait voir des candidatures très impersonnelles, envoyées en deux clics pour atteindre son quotas de bonne conscience dans la recherche d’emploi.

On vous parle de grande société alors qu’on est une socitété de 4 personnes. On vous envoie un CV sans savoir ce que la personne recherche (un poste de freelancer ? salarié ? à Paris ? dans toute l’Europe ?, etc.).

Et si j’ai le malheur de demander des détails avant d’avancer dans le processus c’est silence. L’avantage c’est que si j’oublie de répondre à une candidature, je n’entends rien car il n’y a aucun suivi du côté du candidat. lol

Alors s’il vous plaît clarifiez vos objectifs professionnels avant de postuler. Ciblez vos candidatures. Cela vous facilitera la tâche pour mieux connaître la société qui vous intéresse et faire un suivi. N’hésitez pas à de contacter directement la société pour avoir des précisions avant même de postuler.

96. Ce stage est-il fait pour moi ? 6 questions à se poser.

97. Quelle rémunération pour mon stage ?

98. 6 conseils pour un CV SAS débutant

99. Le SAS vous captive ? 8 astuces pour le montrer dans un CV

100. 6 conseils pour un CV bilingue anglais

101. 8 compétences pour un CV grâce aux loisirs

102. Emploi : Consultants SAS / Freelancers (H/F)

h1

Combien de contrats ai-je au total ? (5/5) PROC TABULATE

novembre 24, 2008

Ce dernier article de notre série sur le calcul d’un total par variable (contrat) sous SAS aborde la procédure PROC TABULATE. Comme précédemment, les résultats sont redirigés vers un data set.

1. Rappel

La source de la thématique : Cette série d’articles est basée sur une question posée sur le forum de www.commentcamarche.net : vous pouvez retrouver la question d’origine sur leur site.

Les autres articles : Vous pouvez retrouver les précédents articles de la série ici :

Les données :Les données sont sauvegardées dans un data set nommé CONTRATS. Il contient 4 variables :

  • l’identifiant de chaque client CLIENT,
  • le nombre de contrats NB_CNTR et
  • deux variables binaires TEL et HABITAT indiquant si oui ou non les fréquences s’appliquent.

Au total, on compte 9 contrats téléphoniques et 5 contrats d’habitation.

Créer le data set CONTRATS

data contrats;
   input client $ nb_cntr tel habitat;
   datalines;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
;
run;

2. La réponse de PROC TABULATE

Lister les variables dans l’instruction VAR : Dans un premier temps les variables binaires TEL et HABITAT sont listées. Là encore il faut préciser le poids de chaque valeur. L’option WEIGHT introduit la variable NB_CONTR, notre coefficient multiplicateur.

Exprimer le calcul requis dans l’instruction TABLE : Pour chacune des variables TEL et HABITAT, la somme est faite en tenant compte du coefficient. Les résultats sont des nombres entiers mais SAS ajoute par défaut des chiffres après la virgule (des zéros donc ici). Pour s’en débarasser, un format 5. est appliqué aux sommes. La sonne ne devra donc pas être un nombre avec plus de 5 chiffres.

Empêcher l’affichage dans la fenêtre OUTPUT : La sortie générée par PROC TABULATE s’appelle TABLE. Par défaut, le résultat est envoyé dans la fenêtre OUTPUT. Pour empêcher cette redirection le temps du PROC TABULATE, les options ODS EXCLUDE doivent être activées.

Rediriger ses résultats dans un data set avec l’ODS (Output Delivery System) : Le data set contenant les résultats s’appelle SOLUTION5. Il est créé avec l’instruction ODS OUTPUT.

*ods exclude table;
proc tabulate data=contrats;*out=solution5;
   var tel habitat / weight=nb_cntr;
   table tel habitat, (sum='Frequency')*f=5.;
   ods output table=solution5;
run;
*ods exclude none;

L’ancienne méthode pour créer un data set, l’option OUT= : L’ancienne méthodeconsiste à ajouter l’option OUT= dans l’instruction PROC TABULATE. Mais cette syntaxe n’est pas généralisable à toutes les procédures et est donc plus difficile à se souvenir pour des utilisations occasionnelles.

3. Améliorer le fichier de sortie

Un simple PROC PRINT sur le fichier SOLUTION5 montre que

_TYPE_ _PAGE_ _TABLE_ tel_Sum habitat_Sum

   0      1      1        9       5

Pour changer l’orientation des résultats, vous pouvez faire appel à un PROC TRANSPOSE.

proc transpose data=solution5 out=solution5 (drop=_LABEL_);
   var tel_sum habitat_sum;
run;

Reste à vous d’améliorer la présentation avec des RENAME, LABEL appropriés, etc.

  _NAME_     COL1
tel_Sum       9
habitat_Sum   5
h1

Choisir ses couleurs sous SAS

novembre 21, 2008
Prisme de couleurs

www.sasreference.fr

Que vous souhaitiez changer sous SAS la couleur d’un titre, la couleur d’une cellule dans un tableau sous Word ou Excel, ou la couleur des barres dans un diagramme en barre, il vous faudra retrouver le nom des couleurs.

Quelques unes, très basiques, ont des pseudonymes compréhensibles par l’homme au premier coup d’oeil. On parle de black (noir), white (blanc), yellow (jaune), red (rouge), green (vert), blue (bleu), etc. Dans l’article qui suit, je vous propose d’élargir votre éventail de couleurs au prisme affiché en début d’article.

1. Tester les couleurs

Pour illustrer les couleurs, je choisi de créer un fichier .rtf (lisible par Word). Dedans, sont affichées les données du data set CLASS situé dans la bibliothèque SASHELP. Un titre précède ce tableau. C’est la couleur de ce titre qui va être changée.

Créer un document .RTF : Pour créer le document .RTF, j’utilise la syntaxe de l’Output Delivery System (ODS) et plus particulièrement les instructions ODS RTF.

Un titre dans le corps du document : Souhaitant voir le titre dans le corps du document et non dans l’en-tête, j’ajoute l’option BODYTITLE.

Ajouter un titre : Pour définir le titre et une couleur autre que celle par défaut (noir), l’instruction TITLE avec son option COLOR= est donné.

ods rtf file='C:/sasref/title_color.rtf' bodytitle;
   title color=cxFF6600 'Le data set CLASS de la bibliothèque SASHELP';
   proc print data=sashelp.class;
   run;
ods rtf close;

Avec ce code, le titre est orangé.

color_example

2. Une couleur composée de nuances de rouge, vert et bleu

La couleur orangée de l’exemple a été créée à partir du code CXFF6600. A moi à présent de vous expliquer ce code afin que vous puissiez l’adapter aux couleurs de votre choix. Il faut couper ce code en 4 pour comprendre son sens : CX, FF, 66, 00.

CX : Les lettres CX introduisent une couleur du type RGB. Entendez par RGB, Red/Green/Blue ou en français rouge/vert/bleu. Il va donc s’agit de faire un savant dosage de ces trois couleurs. Ces trois couleurs sont introduites par des codes à deux caractères. Ici, Rouge=FF, Vert=66 et Bleu=00.

256 valeurs par couleur : Chaque dosage peut prendre 256 valeurs différentes. En effet, il s’agit de combiner 16 valeurs (0, 1, 2, 3, 4, 5, 6, 7, 8, A, B, C, D, E, F) pour former des codes à 2 caractères. Les valeurs vont donc de 00, 01,… à FD, FE, FF.

  • Rouge : Le rouge varie entre un couleur noir (RED=00) et une rouge très vif (RED=FF)
  • Vert : Le vert varie entre un couleur noir (GREEN=00) et une vert très vif (GREEN=FF)
  • Bleu : Le bleu varie entre un couleur noir (BLUE=00) et une rouge très vif (BLUE=FF)

 Un mélange de blanc et noir :

  • Blanc : Si vous mettez la couleur les couleurs les plus vives ensemble (RED=FF, GREEN=FF et BLUE=FF), vous obtenez du blanc.
  • Noir : A l’inverse, si vous mettez les couleurs les plus sombres ensemble (RED=00, GREEN=00, BLUE=00), vous obtenez du noir.
  • Gris : les nuances de gris s’obtiennent en utilisant le même dosage de rouge, vert et bleu. Ainsi CXDDDDDD sera un gris très clair alors que CX101010 sera très foncé.

3. Passer de chiffres 0-255 à des codes à deux chiffres 00-FF

Vous pouvez retrouver les valeurs allant de 0 à 255 sous Excel par exemple. Mais comment savoir à quoi correspond 102 par exemple lorsqu’on utilise les codes allant de 00 à FF ? Je vous ai donc reconstitué un petit code pour faire le rapprochement.

proc format;
   value colorfmt 10='A'
                  11='B'
                  12='C'
                  13='D'
                  14='E'
                  15='F';
run;

data color_code (drop=i j);
   do i=0 to 15;
      do j=0 to 15;
	color_lst=cat(put(i,colorfmt.),put(j,colorfmt.));
         output;
      end;
   end;
run;

proc print data=color_code;
run;

4. Les nuances de gris

Voici donc une liste de grisés :

rouge   vert    bleu    cx_color

255     255      255    CXFFFFFF (blanc)
248     248      248    CXF8F8F8
234     234      234    CXEAEAEA
221     221      221    CXDDDDDD
192     192      192    CXC0C0C0
178     178      178    CXB2B2B2
150     150      150    CX969696
128     128      128    CX808080
119     119      119    CX777777
 95      95       95    CX5F5F5F
 77      77       77    CX4D4D4D
 41      41       41    CX292929
 51      51       51    CX333333
 28      28       28    CX1C1C1C
 17      17       17    CX111111
  8       8        8    CX080808
  0       0        0    CX000000 (noir)

5. Retrouver les couleurs du prisme

Le prisme en haut de la page contient 12 lignes. Voici pour chacune de ces lignes (de haut en bas et de gauche à droite) les couleurs rouge, vert et bleu qui composent chaque case ainsi que le code à utiliser par SAS.

position rouge   vert    bleu    cx_color

Ligne 1

 1      0      51      102    CX003366
 2     51     102      153    CX336699
 3     51     102      204    CX3366CC
 4      0      51      153    CX003399
 5      0       0      153    CX000099
 6      0       0      204    CX0000CC
 7      0       0      102    CX000066

Ligne 2

 1      0     102      102    CX006666
 2      0     102      153    CX006699
 3      0     153      204    CX0099CC
 4      0     102      204    CX0066CC
 5      0      51      204    CX0033CC
 6      0       0      255    CX0000FF
 7     51      51      255    CX3333FF
 8     51      51      153    CX333399

Ligne 3

 1      0     128      128    CX008080
 2      0     153      153    CX009999
 3     51     204      204    CX33CCCC
 4      0     204      255    CX00CCFF
 5      0     153      255    CX0099FF
 6      0     102      255    CX0066FF
 7     51     102      255    CX3366FF
 8     51      51      204    CX3333CC
 9    102     102      153    CX666699

Ligne 4

 1     51     153      102    CX339966
 2      0     204      153    CX00CC99
 3      0     255      204    CX00FFCC
 4      0     255      255    CX00FFFF
 5     51     204      255    CX33CCFF
 6     51     153      255    CX3399FF
 7    102     153      255    CX6699FF
 8    102     102      255    CX6666FF
 9    102       0      255    CX6600FF
10    102       0      204    CX6600CC

Ligne 5

 1     51     153       51    CX339933
 2      0     204      102    CX00CC66
 3      0     255      153    CX00FF99
 4    102     255      204    CX66FFCC
 5    102     255      255    CX66FFFF
 6    102     204      255    CX66CCFF
 7    153     204      255    CX99CCFF
 8    153     153      255    CX9999FF
 9    153     102      255    CX9966FF
10    153      51      255    CX9933FF
11    153       0      255    CX9900FF

Ligne 6

 1      0     102        0    CX006600
 2      0     204        0    CX00CC00
 3      0     255        0    CX00FF00
 4    102     255      153    CX66FF99
 5    153     255      204    CX99FFCC
 6    204     255      255    CXCCFFFF
 7    204     236      255    CXCCECFF
 8    204     204      255    CXCCCCFF
 9    204     153      255    CXCC99FF
10    204     102      255    CXCC66FF
11    204       0      255    CXCC00FF
12    153       0      204    CX9900CC

Ligne 7

 1      0      51        0    CX003300
 2      0     128        0    CX008000
 3     51     204       51    CX33CC33
 4    102     255      102    CX66FF66
 5    153     255      153    CX99FF99
 6    204     255      204    CXCCFFCC
 7    255     255      255    CXFFFFFF
 8    255     204      255    CXFFCCFF
 9    255     153      255    CXFF99FF
10    255     102      255    CXFF66FF
11    255       0      255    CXFF00FF
12    204       0      204    CXCC00CC
13    102       0      102    CX660066

Line 8

 1     51     102        0    CX336600
 2      0     153        0    CX009900
 3    102     255       51    CX66FF33
 4    153     255      102    CX99FF66
 5    204     255      153    CXCCFF99
 6    255     255      204    CXFFFFCC
 7    255     204      204    CXFFCCCC
 8    255     153      204    CXFF99CC
 9    255     102      204    CXFF66CC
10    255      51      204    CXFF33CC
11    204       0      153    CXCC0099
12    128       0      128    CX800080

Ligne 9

 1     51      51        0    CX333300
 2    102     153        0    CX669900
 3    153     255       51    CX99FF33
 4    204     255      102    CXCCFF66
 5    255     255      153    CXFFFF99
 6    255     204      153    CXFFCC99
 7    255     153      153    CXFF9999
 8    255     102      153    CXFF6699
 9    255      51      153    CXFF3399
10    204      51      153    CXCC3399
11    153       0      153    CX990099

Ligne 10

 1    102     102       51    CX666633
 2    153     204        0    CX99CC00
 3    204     255       51    CXCCFF33
 4    255     255      102    CXFFFF66
 5    255     204      102    CXFFCC66
 6    255     153      102    CXFF9966
 7    255     124      128    CXFF7C80
 8    255       0      102    CXFF0066
 9    214       0      147    CXD60093
10    153      51      102    CX993366

Ligne 11

 1    128     128        0    CX808000
 2    204     204        0    CXCCCC00
 3    255     255        0    CXFFFF00
 4    255     204        0    CXFFCC00
 5    255     153       51    CXFF9933
 6    255     102        0    CXFF6600
 7    255      80       80    CXFF5050
 8    204       0      102    CXCC0066
 9    102       0       51    CX660033

Ligne 12

 1    153     102       51    CX996633
 2    204     153        0    CXCC9900
 3    255     153        0    CXFF9900
 4    204     102        0    CXCC6600
 5    255      51        0    CXFF3300
 6    255       0        0    CXFF0000
 7    204       0        0    CXCC0000
 8    153       0        0    CX990000

Ligne 13

 1    102      51        0    CX663300
 2    153     102        0    CX996600
 3    204      51        0    CXCC3300
 4    153      51        0    CX993300
 5    153       0        0    CX990000
 6    128       0        0    CX800000
 7    165       0       33    CXA50021

Résumé des 13 lignes de couleurs

h1

Combien ai-je de contrats au total ? (4/5) PROC FREQ

novembre 17, 2008

Dans les précédents articles sur cette série traitant du calcul de totaux, la procédure PROC SQL, le RETAIN dans une étape DATA et la procédure PROC MEANS nous on montré qu’elles pouvaient retrouver le nombre total de contrats pour chaque type (contrats téléphoniques, contrats d’habitation). La procédure PROC FREQ mérite également votre attention . Comme PROC MEANS, cette procédure utilise la notion de coefficient/poid (weight).

Rappel : Vous pouvez retrouver l’étape data créant le data set pour ce sujet en fin d’article. Les données contiennent l’identifiant du client CLIENT, le nombre de contrats NB_CNTR et deux variables binaires TEL et HABITAT indiquant si oui ou non les fréquences s’appliquent. Au total, on compte 9 contrats téléphoniques et 5 contrats d’habitation.

client nb_cntr tel habitat;
   a      5     1     0
   b      1     1     0
   c      2     0     1
   d      1     1     0
   e      3     0     1
   f      2     1     0

1. Deux approches possibles

Avec la procédure PROC FREQ, deux options s’offrent à vous :

  • D’abord générer un data set par type de contrat avec PROC FREQ et ensuite combiner les données.
  • D’abord changer la structure des données et ensuite obtenir un seul data set avec PROC FREQ.

Par soucis de simplicité, je vous propose d’aborder la seconde méthode qui me semble de loin la plus logique pour nos données.

Etape 1 : Changer la structure des données revient à avoir d’un côté le nom des différents types de contrats et de l’autre si oui ou non une fréquence s’applique pour eux. Il n’y a alors plus qu’une seule variable binaire.

Pour changer cette structure des données, deux solutions sont possibles :

  • une étape data ou
  • la procédure PROC TRANSPOSE.

La première approche servira à comprendre la manipulation. La seconde approche est facilement généralisable à un plus grand nombre de variable et a donc ma préférence.

Etape 2 : Pour extraire le data set avec PROC FREQ, il existe l’ancienne méthode avec l’option OUT= et la nouvelle beaucoup plus standard ODS OUTPUT. Le raisonnement appliqué par cette méthode est applicable à de nombreuses procédure. La syntaxe est donc beaucoup facile de la retenir.

2. Etape 1 – Changer la structure des données en utilisant une étape data

Il s’agit de créer une variable unique indiquant si oui ou non les coefficients (weight) données dans la variable NB_CNTR s’appliquent.

data contrats_update ;
   length contrat $7;
   set contrats (in=a keep=nb_cntr tel     rename=(tel=tmp)     )
       contrats (     keep=nb_cntr habitat rename=(habitat=tmp) );
    if a then contrat='tel';
    else contrat='habitat';
run;

Les 6 premières lignes sont consacrées au contrat de téléphone et les 6 dernières concernent les contrats d’habitation.

Seules les données où la variable binaire est oui (NO_YES=1) seront au final intéressante. Il est possible de supprimer les données où NO_YES=0 en ajoutant dans l’étape data un WHERE (where=(no_yes=1)) et en supprimant ensuite la variable NO_YES avec DROP (data contrats_update (drop=no_yes)). Voulant vous montrer les différentes étapes, je n’ai pas supprimé les lignes ou NO_YES=0.

nb_cntr  no_yes    contrat

   5        1        tel
   1        1        tel
   2        0        tel
   1        1        tel
   3        0        tel
   2        1        tel
   5        0        habitat
   1        0        habitat
   2        1        habitat
   1        0        habitat
   3        1        habitat
   2        0        habitat

3. Etape 1 alternative – chpour regrouper les contrats dans une seule variable : PROC TRANSPOSE

Pourquoi un PROC SORT ? Dans cette section, il est fait usage de la procédure PROC TRANSPOSE pour modifier la structure du data set de départ. Comme une instruction BY est nécessaire, il est obligatoire d’avoir au préalable les données triées dans ce même ordre. Ceci explique la présence actuelle de la procédure PROC SORT.

Pourquoi une option OUT= ? une Ne souhaitant pas ajouter ces changement dans le fichier d’origine, j’ai donné le nom CONTRATS_UPDATE au nouveau data set. C’est un choix personnel pour cet article en particulier. Il n’y a aucune raison pour immiter obligatoirement ce choix.

proc sort data=contrats out=contrats_update;
   by client nb_cntr;
run;

L’objectif est d’avoir à présent autant de lignes que de type de contrats (2 lignes par client dans notre exemple). Pour chaque ligne est donné le nombre de contrats pouvant s’appliquer (variable NB_CONTR) et si oui ou nom ce nombre s’applique (variable NO_YES).

proc transpose data=contrats_transp
               out=contrats_transp (drop=client
                                    rename=(_name_=contrat col1=no_yes));
   by client nb_cntr;
   var tel habitat;
run;

Après avoir renommé les variables _NAME_ et COL1, nous retrouvons le même résultat que précédemment à l’exception de l’ordre dans lequel sont triées les données. Mais cela n’a pas d’effet dans notre PROC FREQ à venir.

    nb_cntr    contrat    no_yes

       5       tel         1
       5       habitat     0
       1       tel         1
       1       habitat     0
       2       tel         0
       2       habitat     1
       1       tel         1
       1       habitat     0
       3       tel         0
       3       habitat     1
       2       tel         1
       2       habitat     0

4. Etape 2 – Exécuter un PROC FREQ

ODS EXCLUDE ? Je souhaite créer un data set et seulement un data set. Hors par défaut le résultat (la sortie) est envoyé dans la fenêtre OUTPUT. L’instruction ODS EXCLUDE de début empêche cet envoi et celle de fin rétablit le statut initial.

ONEWAYFREQS ? Dans le cadre d’un tableau à une dimension, la sortie s’appelle ONEWAYFREQS. Un ODS TRACE ON/LISTING permet de retrouver lors d’une première exécution ce nom si vous avez oublié dans la fenêtre output (ODS TRACE OFF pour arrêter le processus).

ODS OUTPUT ? La sortie est envoyée dans le data set SOLUTION4 en se servant de l’instruction ODS OUTPUT et du nom de la sortie. Seules les variables CONTRAT et FREQUENCY sont conservées.

L’ancienne méthode ? En commentaire, vous trouverez l’option OUT= de l’instruction TAB qui vous fournira les mêmes statistiques. A noter que le nom de la variable pour les fréquences s’appelle cette fois COUNT et non plus FREQUENCY.

ods exclude onewayfreqs;
proc freq data=contrats_update (where=(no_yes=1));
   weight nb_cntr;
   by contrat;
   table no_yes;
   ods output onewayfreqs=solution4 (keep=contrat frequency);
   *table tmp/out=solution4 (keep=contrat count);
run;
ods exclude none;

Au final, on retrouve bien 9 contrats téléphoniques et 5 contrats d’habitation.

contrat Frequency

tel         9
habitat     5

Annexe : entrer les données dans un tableau SAS

data contrats;
   input client $ nb_cntr tel habitat;
   datalines;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
;
run;
h1

7 conseils pour collaborer avec un programmeur SAS

novembre 13, 2008

Vous devez travaillez avec programmeur SAS et souhaitez connaître quelques petits trucs qui faciliteront cette collaboration. Cet article est fait pour vous. Les exemples traiteront principalement de la pharmaceutique mais peuvent être aisément généralisés.

1. Répondez rapidement à leurs questions

Maintenez le flux d’information : Lorsqu’un programmeur pose une question, il a souvent besoin de la réponse immédiatement pour pouvoir continuer à avancer dans son travail. Vous avez à peu prêt une marge d’une demi-journée pour réponse. Si vous répondez dans les 5 minutes c’est encore mieux. Faute de réponse, il sera obligé d’arrêter de travailler sur le projet. Le temps de réimmersion dans un projet est long et pesant pour un programmeur. En effet, le programmeur oublie très rapidement ce qu’il a fait et pourquoi même si il documente ces programmes. Imposez lui ces contraintes et il sera encore moins enclin à reprendre le processus et c’est vous qui risquez de voir vos dates butoires passer aux oubliettes.

2. Coupez vos réponses

Ecrire un mail par problématique vous donnera plus de chance d’en voir une partie de traitées rapidement. Si vous envoyez un bloc, cela effrayera le programmeur. Il aura tendance à traiter les réponses simples et rapide en premier. Faites partie de ses priorités.

3. Soyer précis dans vos demandes

Apportez votre expertise sur les données : Bien sûr, vous ne connaissez pas tous les surprises dans les données qui seront visibles une fois seulement le travail du programmeur en partie accomplie. Néanmoins, vous êtes le spécialiste sur ces données. Vous savez quand des valeurs sont aberrantes, comment les variables doivent être définies.

4. Garder un document de référence commun

Encouragez le programmeur à rédiger un document résumant les choix qu’il fait lors de l’écriture de ses programmes. Dans le cas de la rédaction d’une macro, il est obligé d’écrire divers documents :

  • un document technique (specification)
  • un manuel utilisateur (user manual)
  • un récapitulatif des tests effectués (test plan)
  • un diagramme décrivant le processus du programme (flowchart).

A tord, il rédige souvent ce type de document après avoir fini la partie programmation. Incitez-le à commencer la rédaction dès le début et à poursuivre les mises à jour au fur-et-à mesure.

Reste que dans le cas de la programmation lié au transfert de données ou à la création de tables statistiques aucun document n’est souvent demandé. Les Statistical Analysis Plan (SAP) pour les tables statistiques ne sont pas encore généralisées. Il est très pratique d’avoir un document sur lequel le programmeur listera les choix fais, les points en suspend demandant clarification de votre part, etc.

5. Informez-le des délais à respecter et vos attentes

Informez-lui de l’agenda de l’étude, des décisions majeures : Tenez compte du fait que le programmeur n’est impliqué que sporadiquement dans une étude clinique. Il sera consulté seulement à une certaine période du processus. Il n’aura quasiment pas d’information sur l’étude à part le protocole. Il n’aura pas été invité aux réunions pour présenter les enjeux de l’études, pour écouter les discussions sur les spécificités des patients et n’est en général pas tenu au courant des résultats de l’études à part un : les résultats sont positifs ou pas. De plus, il remplacera parfois un autre programmeur en cours de projet ou sera remplacé par un autre.

6. Expliquez les enjeux du projet

Faites-lui partager vos motivations et les enjeux que représentent l’étude sur laquelle vous l’impliquez. Le programmeur doit travailler sur plusieurs études et projets à la fois. Il n’a pas donc les moyens de se motiver pour chaque particularité d’une étude.

7. Ne modifiez pas le travail effectué par le programmeur

Si vous ne vous sentez pas à l’aise avec la programmation sous SAS, ne commencez pas à ajouter des programmes qui affecteront les travaux de votre programmeur. Respectez le rôle de chacun.

h1

Combien de contrats ai-je au total ? (3/5) PROC MEANS

novembre 10, 2008

Dans nos précédents articles du lundi, nous avons vu avec PROC SQL et RETAIN deux approches pour calculer le nombre total de contrats à partir du nombre de contrats par client. Il s’agit alors de résoudre une question posée sur le forum commentcamarche.net. Les données ont qu’en à elle une structure très particulière. La procédure PROC MEANS offre une troisième réponse possible comme nous le verrons ici.

Les données : Vous trouverez en fin d’article un rappel des données.

  • CLIENT : l’identifiant du client,
  • NB_CNTR : le nombre de contrats,
  • TEL: variable binaire (0/1) indiquant si oui ou non le nombre de contrat s’applique aux contrats téléphoniques du client
  • HABITAT : variable binaire (0/1) indiquant si oui ou non le nombre de contrat s’applique aux contrats habitation du client

1. La notion de coefficient (WEIGHT)

Les coefficient au bac : Les bacheliers français se souviendront d’avoir appliqué des coefficients à leur notes pour savoir combien de points ils leur fallait pour avoir le fameux sésam du bac. Il fallatt ainsi compter 5 fois la note d’histoire-géographie si le coefficient est de 5, etc.

La même notion de coefficient concerne aussi les bases de données. Il faut compter 5 fois une observation lorsqu’un coefficient de 5 est appliqué. En effet de manière générale, les données à disposition du programmeur contient soit toutes les informations ou un résumé de ces informations.

Traduction : En anglais, on parle de weight pour désigner les coefficient. En effet, le poids de chaque observation est mesuré.

Pourquoi utiliser des coefficients : Dans le cas d’un data set contenant des informations sur les contrats de cliens, une table pourrait avoir :

  • une ligne pour chaque contrat de chaque client ou
  • une ligne par client et le nombre de contrats qu’il a.

Dans le second cas, il y a une perte d’information pour les autres variables du data set mais le data set est moins volumineux.

Le mot-clé WEIGHT en SAS : De son côté, SAS utilise dans plusieurs procédures statistiques (PROC MEANS, PROC FREQ, etc.) le mot WEIGHT en tant que :

  • instruction,
  • option dans une instruction.

2. La notion de coefficient appliquée à nos données

WEIGHT=NB_CNTR : Dans notre exemple, la variable NB_CNTR indique combien de contrats un client a. Il s’agit de la variable servant de coefficient (weight).

client nb_contr tel habitat
   a       5     1     0
   b       1     1     0
   c       2     0     1
   d       1     1     0
   e       3     0     1
   f       2     1     0

Lister les variables concernées par le coefficient : SAS applique ce poids aux deux variables binaires TEL et HABITAT.

La variable TEL sera interprétée de la manière suivante :

client tel
   a    5
   b    1
   c    0
   d    1
   e    0
   f    2

Et la variable HABITAT sera interprétée ainsi :

client habitat
   a     0
   b     0
   c     2
   d     0
   e     3
   f     0

La syntaxe minimale du PROC MEANS : La procédure PROC MEANS listera dans un premier temps les variables binaires. Puis en option, désignera la variable weight afin de savoir par combien chaque valeur doit être multipliée.

proc means data=contrats sum;
   var tel habitat / weight=nb_cntr;
run;

L’option statistique SUM : pour ne voir que la somme des contrats il faut précise la statistique SUM en option de l’instruction PROC MEANS. Sinon, seont affichés les statistiques par défaut que sont

  • le nombre de contrat (N),
  • le plus petit/grand nombre de contrats (MIN/MAX),
  • la moyenne (MEAN) et
  • l’écart type (STD).

Résultats : Les premiers résultats dans la fenêtre OUTPUT confirme qu’il y a 9 contrats téléphoniques et 5 contrats d’habitation au total.

The MEANS Procedure
Variable            Sum
------------------------
tel            9.0000000
habitat        5.0000000
------------------------

2. Gérer les sorties de l’ODS

Par défaut les résultats sont redirigés vers la fenêtre OUTPUT de SAS.

Ajouter une destination avec ODS OUTPUT : Afin d’extraire le résultat dans un data set, il est possible d’ajouter une instruction ODS OUTPUT. Pour connaître le nom désignant la sortie générée par un PROC MEANS, utilisez au préalable ODS TRACE ON/LISTING et ODS TRACE OFF.

Stopper la destination OUTPUT avec ODS EXCLUDE : Si, de plus, le programmeur souhaite empêcher l’affichage de la sortie PROC MEANS dans la fenêtre OUTPUT, l’instruction ODS EXCLUDE doit être exécutée (ODS SELECT ALL annulera l’opération).

*ods trace on/listing;
proc means data=contrats sum;
   var tel habitat / weight=nb_cntr;
   ods exclude summary;
   ods output summary=solution3;
run;
*ods trace off;

Une version de base des statistiques sauvegardées dans un data set : Après un PROC PRINT sur le data set nouvellement créé (SOLUTION3), la sortie se présente sous une forme différente que dans la fenêtre OUTPUT.

VName_           VName_
 tel    tel_Sum  habitat  habitat_Sum

 tel       9     habitat      5

Pour modifier cette présentation, il est possible d’utiliser un PROC TRANSPOSE.

proc transpose data=solution3 out=solution3 (drop=_LABEL_);
   var tel habitat;
run;

Une version améliorée des statistiques sauvegardées dans un data set : Reste à vous le choix de renommer le nom des variables selon vos préférences.

  _NAME_    COL1
tel_Sum       7
habitat_Sum   5

Annexe :

data contrats;
   input client $ nb_cntr tel habitat;
   datalines;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
;
run;

Plus de précisions sur la procédure PROC MEANS sont disponibles en ligne : SAS Online Doc : The MEANS Procedure.

A dans huit jours, pour une présentation de l’approche avec PROC FREQ. D’ici là je vous retrouve d’ici quelques jours pour le second article de la semaine.

h1

Lire des données d’un fichier .TXT sans perdre d’information (les options d’INFILE)

novembre 7, 2008

L’accès à des données contenues dans un fichier externe du type .TXT se fait sous SAS par l’intermédiaire d’une étape data et de l’instruction INFILE. Plusieurs options sont possibles pour cette instruction. Il est important de connaître les forces et faiblesses de chacune afin de faire le bon choix. Cet article vous présentera dans un premier temps le fichier .TXT qui servira d’exemple. En premier lieu, il sera appelé avec l’option FLOWOVER, l’option par défaut. Puis, cela sera le tour des options TRUNCOVER et MISSOVER/PAD.

1. Aperçu sur les données contenu dans le fichier .TXT

Afin de montrer les nuances entre les options FLOWOVER, TRUNCOVER et MISSOVER, un fichier EG_INFILE.TXT est créé. Ce fichier contient les données pour deux variables caractères CNTRY (country) et CNT (count).

Dans l’aperçu qui suit, j’ai remplacé les espaces par des points afin de vous puissiez visualiser la différence que peuvent créer certains espaces.

  • La première ligne contient 2 caractères
  • Les seconde et troisième lignes contiennent 12 caractères
  • L’avant dernière ligne n’en contient que 4
  • La dernière en contient 12 si on inclus les espaces de fin.

Note : “e.g.” est la version raccourcie de “example” en anglais. C’est donc notre équivalent de “ex”.

IT
CA.12.......
BE.123456789
KR.
MY.2
FI.1........

Le choix du FILENAME : Par choix, je crée un mot SASREF qui désigne le chemin d’accès au fichier EG_INFILE.TXT. Cela évitera d’avoir à recopier le chemin dans chaque étape data. Toute mise à jour ou correction du chemin d’accès se fera en une seule fois évitant tout oubli.

filename sasref 'C:/sasref/eg_infile.txt';

Note : Il est important de définir une longueur pour les variables caractères. Sinon les variables ayant plus de 8 caractères sont tronquées. Dans notre cas, la valeur 123456789 deviendrait 12345678.

2. FLOWOVER, l’option par défaut

Par défaut, SAS applique l’option FLOWOVER avec une instruction INFILE. Ainsi l’instruction INFILE mise en commentaire, en ajoutant une étoile en tête d’instruction, donnerait le même résultat que celle active.

data eg_flowover;
   infile sasref;
   *infile sasref flowover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

L’aperçu qui suit montre très clairement que SAS continu sa lecture sur la ligne suivante s’il n’a pas trouvé une valeur pour chaque variable dans la ligne actuelle.

  • Créer la première ligne d’observations : En ligne 1, il manque une valeur pour CNT. SAS va en ligne deux et récupère la première valeur. Il ignorera toutes les valeurs qui peuvent exister sur le reste de la ligne. Il lui a donc fallu deux lignes en entrée pour créer une ligne en sortie.
  • Créer la seconde ligne d’observations : après avoir lu les deux premières lignes, SAS passe à la troisième ligne pour créer la seconde ligne d’observations. Il trouve son bonheur ici puisqu’il y a une valeur par variable.
  • Créer la troisième ligne d’observations : à la ligne suivante, il manque de nouveau une valeur. SAS assigne la valeur KR à la variable CNTRY. Mais ne trouvant pas de valeur pour la variable CNT, il passe à la ligne suivante et trouve la valeur MY.
  • Créer la quatrième et dernière ligne d’observations : il ne reste a SAS plus qu’une ligne de disponible dans le fichier d’entrée. Cette ligne contient une observation par variable. SAS est content avec.
cntry  cnt

  IT   CA
  BE   123456789
  KR   MY
  FI   1

3. L’option TRUNCOVER empêche le passage à la ligne et ne se formalise pas des longueurs

L’option TRUNCOVER palie à ce problème en empêchant à SAS d’aller voir à la ligne suivante

data eg_truncover;
   infile sasref truncover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

Le résultat est comme escompté : 

cntry   cnt
  IT
  CA    12
  BE    123456789
  KR
  MY    2
  FI    1

4. L’option MISSOVER empêche le passage à la ligne

Les limites de l’option MISSOVER avec un INFILE : L’option MISSOVER est une autre option possible de l’instruction INFILE. Elle présente néanmoins une limite due à des espaces.

data eg_missover;
   infile sasref missover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

Dans l’exemple, la valeur de CNT (2) quand CNTRY=MY disparaît, alors quela valeur de CNT (1) quand CNTRY=FI reste. Alors que la Qu’est ce qui a provoqué cela ?

Vous souvenez vous de la remarque concernant les espaces en fin de ligne dans la première section de cette article. SAS recherche 9 caractères pour créer une valeur pour CNT. Hors quand CNTRY=MY, il n’en trouve qu’un. Cela ne le satisfait pas. Comme, avec MISSOVER, il ne peut pas aller voir sur la ligne d’après. Il se contente de mettre une valeur manquante.

cntry   cnt

  IT   
  CA    12
  BE    123
  KR   
  MY   
  FI    1

L’équivalent de TRUNCOVER : L’option MISSOVER en combinaison avec l’option PAD fournira le même résulat que l’option TRUNCOVER. Autant donc utiliser un seul mot en la personne de TRUNCOVER.

data eg_missover_pad;
   infile sasref missover pad;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
run;

Le cas particulier du DATALINES : MISSOVER avec un DATALINES ne rencontre pas le problème des blancs de fin de ligne manquants.

data eg_missover;
   infile datalines missover;
   length cntry $2 cnt $9;
   input cntry $ cnt $;
   datalines;
IT
CA 12
BE 123456789
KR
MY 2
FI 1
;
run;

Conclusion

Nous avons vu un cas particulier de l’instruction INFILE : lecture d’un fichier dans lequel chaque ligne est sensée représenter une ligne d’observations.

Par défaut, SAS recherche autant d’emplacements (texte ou espaces) dans le fichier qu’il lit que celui donné par la longueur d’une variable. Faute de quoi SAS jetera un coup d’oeil à la ligne suivante (FLOWOVER) ou ignorera certaines valeurs (MISSOVER) selon l’option indiquée dans l’instruction INFILE.

L’option TRUNCOVER répond aux deux problèmes (passage à la ligne et manque de place sur une ligne). Il est donc judicieux de privilégier l’option TRUNCOVER sur MISSOVER pour ce problème précis.

h1

Combien de contrats ai-je au total ? (2/5) RETAIN

novembre 3, 2008

Après un premier article faisant appel à la procédure SQL pour identifier le nombre total de contrats d’un type donné à partir d’un data set SAS, voici comment un compteur dans une étape data peut résoudre le problème.

1. Renommer des variables

  • Avoir les mêmes noms en entrée et en sortie : Dans le cas présent, il faut définir de nouvelles variables ayant un nom différent de ceux existant. Pour avoir quand même au final le même nom qu’au départ, j’ai choisi de renommer mes variables d’origines rendant leur ancien nom de nouveau disponible.
  • Quel nom pour les variables ? Ces variables portent un nom commençant par un tiret bas (underscore). Cela permet d’avoir un nom toujours parlant et de les supprimer rapidement avec _: (supprimer toutes les variables commençant par un tiret bas).
data solution2 (drop=_: );
   set contrats (rename=(tel=_tel
                         habitat=_habitat);
   *...;
run;

D’autres variables sont supprimées :

  • La variable CLIENT disparaît dès de départ car il ne sert pas dans notre cas.
  • La variable NB_CNTR disparaît seulement à la fin car elle va servir pour faire nos calculs.
data solution2 (drop=_: nb_contr);
   set contrats (drop=client
                 rename=(tel=_tel
                         habitat=_habitat);
   *...;
run;

2. Créer un compteur

Une fois les variables d’origine renommées, les variables TEL et HABITAT sont initialisées à 0 avec un RETAIN. Cela veut dire que pour toutes les observations, ces variables ont dans un premier temps la valeur 0. SAS lit les observations les une après les autres. A chaque fois qu’une valeur de TEL est changée toutes celles qui suivent le sont aussi. C’est le principe du RETAIN.

data solution2 ;*(...);
   set contrats ;*(...);
   retain tel 0
          habitat 0;
   tel     = tel     + nb_cntr * _tel;
   habitat = habitat+  nb_cntr * _habitat;
run;

SAS initialise les variable TEL et HABITAT : Tout d’abord TEL=0 et HABITAT=0.

nb_cntrt _tel _habitat tel habitat
    5      1      0     0     0
    1      1      0     0     0
    2      0      1     0     0
    1      1      0     0     0
    3      0      1     0     0
    2      1      0     0     0

SAS lit la première ligne du data set : A la lecture de la première ligne du data set CONTRATS, la variable TEL est mise à jour. Sachant que pour la première observation, il a 5 contrats (NB_CNTRT=5 et _TEL=1), la première valeur de TEL est égale à 5 et toutes celles qui suivent aussi.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     5     0
    2      0      1     5     0
    1      1      0     5     0
    3      0      1     5     0
    2      1      0     5     0

SAS lit la seconde ligne du data set : A la lecture de la seconde observation, on ajoute 1*1 à 5. Le résultat (la valeur 6) se répercute sur toutes les observations de la variable TEL.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     6     0
    2      0      1     6     0
    1      1      0     6     0
    3      0      1     6     0
    2      1      0     6     0

SAS lit la troisième ligne du data set : A la lecture de la troisième observation, la valeur de TEL ne change pas car on ajoute zéro (0+2*0). Par contre, celle d’HABITAT change.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     6     0
    2      0      1     6     2
    1      1      0     6     2
    3      0      1     6     2
    2      1      0     6     2

A la fin : Au final, le data set a cette forme. Ce qui nous intéresse ici ce sont les valeurs 9 et 5 de la dernière ligne d’observations.

nb_cntrt _tel _habitat tel habitat
    5      1      0     5     0
    1      1      0     6     0
    2      0      1     6     2
    1      1      0     7     2
    3      0      1     7     5
    2      1      0     9     5

3. Garder la dernière observation

A présent, il s’agit de ne garder que la dernière observation. On commence par créer une variable EOF par l’intermédiaire de l’option END= dans l’instruction SET. Le nom de la variable ici fait référence à l’expression End of File. Mais vous êtes libre de choisir le nom qui vous convient.

  • Une option sans parenthèses : On notera que END= est une option de l’instruction SET et non une option du data set CONTRATS. C’est la raison pour laquelle elle n’apparaît pas entre parenthèses.
  • Une option en fin d’instruction : Les options du data set listées entre parenthèses doivent suivre immédiatement le nom du data set. L’option END= ne peut être ajoutée qu’après.

Cette variable (EOT) a deux particularités :

  • Une variable temporaire : D’une part, elle ne sera pas conservée dans le data set final SOLUTION2 ;
  • Une variable binaire : D’autre part, la variable est binaire ; elle prend la valeur 1 pour la dernière observation, 0 autrement.
data solution2 (...);
   set contrats (...) end=eof;
   *retain ...;
   *tel=...;
   *habitat=...;
   if eof then output;
   *if eof=1 then output;
run;

La condition : Dans la condition qui suit, seule la dernière observation d’EOT a la valeur 1. C’est donc la seule qui est retenue dans la condition. Le “=1″ est implicite dans la condition. C’est pour cela que les deux instructions, celle active et celle en commentaire, sont identiques.

L’action basée sur la condition : Le mot OUTPUT redirige la ligne sélection avec la condition dans le data set final SOLUTION2.

A dans huit jours, pour retrouver une solution avec PROC MEANS.

Annexe : Rappel sur les données et l’étape data dans son ensemble :

data contrats;
   input client $ nb_cntr tel habitat;
   datalines;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
;
run;

data solution2 (drop=_: nb_cntr);
   set contrats (drop=client
                 rename=(tel=_tel
                         habitat=_habitat)
                 end=eof;
   retain tel 0
          habitat 0;
   tel     = tel     + nb_cntr * _tel;
   habitat = habitat + nb_cntr * _habitat;
   if eof then output;
run;