<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>proc &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://wordpress.com/tag/proc/</link>
	<description>Feed of posts on WordPress.com tagged "proc"</description>
	<pubDate>Sun, 07 Sep 2008 00:32:14 +0000</pubDate>

	<generator>http://wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[paseando por /proc]]></title>
<link>http://quimicefa.wordpress.com/?p=157</link>
<pubDate>Thu, 04 Sep 2008 17:59:01 +0000</pubDate>
<dc:creator>quimicefa</dc:creator>
<guid>http://quimicefa.wordpress.com/?p=157</guid>
<description><![CDATA[En este post vamos a darnos un paseillo por el sistema de archivos /proc. Desde siempre me había in]]></description>
<content:encoded><![CDATA[<p>En este post vamos a darnos un paseillo por el sistema de archivos /proc. Desde siempre me había intrigrado la cantidad de datos extraños que hay debajo de /proc, así que vamos a dar una vuelta!</p>
<p><a href="http://quimicefa.files.wordpress.com/2008/09/proc.png"><img class="size-medium wp-image-170 alignnone" title="df -a" src="http://quimicefa.wordpress.com/files/2008/09/proc.png?w=300" alt="" width="306" height="62" /></a></p>
<p>Supongamos que tenemos un linux, que está ejecutando una bbdd Oracle. Oracle arranca unos cuantos procesos: para escribir los logs, listener, escribir datos a datafile, monitorizar otros procesos ...<!--more--></p>
<p><code>[root@box /]# ps aux &#124; grep -i oracle<br />
oracle    3920  0.0  0.1 65304 9876 ?        Ssl  Jul18   0:00 /opt/oracle/product/10.2.0/db/bin/tnslsnr LISTENER -inherit<br />
oracle    3978  0.0  0.2 1641684 17144 ?     Ss   Jul18   0:00 ora_pmon_SID<br />
oracle    3980  0.0  0.1 1640508 15408 ?     Ss   Jul18   0:00 ora_psp0_SID<br />
oracle    3982  0.0  0.4 1640508 40768 ?     Ss   Jul18   0:00 ora_mman_SID<br />
oracle    3984  0.0  6.5 1665924 535984 ?    Ss   Jul18   0:11 ora_dbw0_SID<br />
oracle    3986  0.0  0.3 1656068 31744 ?     Ss   Jul18   0:41 ora_lgwr_SID<br />
oracle    3988  0.0  0.6 1642116 49300 ?     Ss   Jul18   0:54 ora_ckpt_SID<br />
oracle    3990  0.0  2.1 1643228 177576 ?    Ss   Jul18   0:22 ora_smon_SID<br />
oracle    3992  0.0  0.2 1640564 22420 ?     Ss   Jul18   0:00 ora_reco_SID<br />
oracle    3994  0.0  0.7 1642200 63436 ?     Ss   Jul18   0:10 ora_cjq0_SID<br />
oracle    3996  0.0  0.9 1643352 76596 ?     Ss   Jul18   0:04 ora_mmon_SID<br />
oracle    3998  0.0  0.3 1640552 25452 ?     Ss   Jul18   0:00 ora_mmnl_SID<br />
oracle    4000  0.0  0.1 1641388 15560 ?     Ss   Jul18   0:00 ora_d000_SID<br />
oracle    4002  0.0  0.1 1641560 14792 ?     Ss   Jul18   0:00 ora_s000_SID<br />
oracle    4006  0.0  0.2 1640516 16692 ?     Ss   Jul18   0:00 ora_qmnc_SID<br />
oracle    4949  0.0  0.2 1640560 18436 ?     Ss   Jul18   0:00 ora_q000_SID<br />
oracle    4951  0.0  0.1 1640540 16048 ?     Ss   Jul18   0:00 ora_q001_SID<br />
oracle    5052  0.0  0.3 1641228 28808 ?     Ss   Jul18   0:06 oracleSID (LOCAL=NO)<br />
oracle   10251  0.0  0.3 1640704 27508 ?     Ss   11:56   0:00 oracleSID (LOCAL=NO)<br />
root     10358  0.0  0.0 52160  808 pts/0    R+   12:53   0:00 grep -i oracle<br />
[root@box /]#</code></p>
<p>¿Realmente oracle necesita todos esos procesos? Vamos a fijarnos en uno, el listener.</p>
<p><code>[root@box /]# pidof tnslsnr<br />
3920</code></p>
<p>Asi que tiene PID 3920 ... vamos al directorio /proc.</p>
<p><code><br />
[root@box ~]# cd /proc/<br />
[root@box proc]# ls<br />
t1      11981  140   6397  6909       dri          misc<br />
10     11983  1893  6404  6910       driver       modules<br />
10081  11984  2     6439  7          execdomains  mounts<br />
1126   11990  3     6448  7124       fb           mtrr<br />
11421  11994  3313  6469  781        filesystems  net<br />
11794  12005  3459  6470  807        fs           partitions<br />
11862  12021  4     6471  9          ide          scsi<br />
11876  12030  4025  6472  95         interrupts   self<br />
11892  12038  4559  6473  9890       iomem        slabinfo<br />
11894  12066  5     6474  acpi       ioports      stat<br />
11900  12677  5428  6489  asound     irq          swaps<br />
11926  12679  5648  6491  buddyinfo  kallsyms     sys<br />
11929  1293   5654  6531  bus        kcore        sysrq-trigger<br />
11930  13147  5983  6552  cmdline    keys         sysvipc<br />
(...)<br />
3920<br />
(...)<br />
</code><br />
Parece que hay un subdirectorio por cada proceso. Veamos qué podemos averiguar de nuestro listener.</p>
<p><code>[root@box proc]# cd 3920/<br />
[root@box 3920]# pwd<br />
/proc/3920<br />
[root@box 3920]# ls<br />
attr     cwd      loginuid  mountstats  seccomp  status<br />
auxv     environ  maps      oom_adj     smaps    task<br />
cmdline  exe      mem       oom_score   stat     wchan<br />
cpuset   fd       mounts    root        statm</code></p>
<p>Hay bastante información relativa al proceso del listener, por ejemplo:</p>
<ul>
<li>"cmdline" representa la línea de comandos con la que se ha arrancado el proceso. En /proc hay otro cmdline, pero ese representa las opciones que se han pasado al kernel para arrancar.</li>
<li>"cwd" es el directorio en el que está el proceso.</li>
<li>"environ" las variables del entorno de ese proceso. Lo mismo que veríamos con la opción "-e" de ps</li>
<li>"exe" el ejecutable del proceso, en este caso es un enlace simblico a /opt/oracle/product/10.2.0/db/bin/tnslsnr</li>
<li>"root" sería el directorio raíz según ese proceso. Puede ser útil para comprobar si un servicio que hemos instalado se está ejecutando en chroot o no.</li>
<li>"fd" son los descriptores de archivo que está accediendo el proceso. Como en Unix todo son archivos esto significa que podemos ver qué ficheros está leyendo/escribiendo, sockets, pipes. sería algo parecido a lo que hace el comando "lsof"</li>
</ul>
<p>Además de estos valores de procesos, dentro de proc hay más archivos para ver o consultar otras cosas como:</p>
<ul>
<li>si las interfaces de red han de hacer "forwarding"</li>
<li>particiones montadas</li>
<li>sistemas de archivos reconocidos por el kernel</li>
<li>tiempo arrancado (uptime)</li>
</ul>
<p>Vale la pena explorar un poco por /proc, es bastante posible que algunas funciones que necesitamos incluir en un script se puedan hacer accediendo directamente a /proc en vez de ejecutar y parsear la salida de algun comando.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Příspěvek no.1 ]]></title>
<link>http://licanus.wordpress.com/?p=8</link>
<pubDate>Tue, 02 Sep 2008 18:10:14 +0000</pubDate>
<dc:creator>licanus</dc:creator>
<guid>http://licanus.wordpress.com/?p=8</guid>
<description><![CDATA[Nazdar bazar,
Takže já sem Pepa a tyhle stránky jsem vytvořil proto, abych publikoval své názo]]></description>
<content:encoded><![CDATA[<p>Nazdar bazar,</p>
<p>Takže já sem Pepa a tyhle stránky jsem vytvořil proto, abych publikoval své názory, nápady a zážitky :-)</p>
<p>Kdo to chce číst ať to čte a kdo ne tak ať čte třeba Hulána :-D</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[See You Next Olympics!]]></title>
<link>http://crazenz.wordpress.com/?p=20</link>
<pubDate>Thu, 28 Aug 2008 22:33:06 +0000</pubDate>
<dc:creator>crazenz</dc:creator>
<guid>http://crazenz.wordpress.com/?p=20</guid>
<description><![CDATA[Amazing Beijing
 
Despite what the detractors say, China has redeemed itself. Beijing was a tremend]]></description>
<content:encoded><![CDATA[<p class="MsoNormal" style="margin:0;"><span style="font-size:15.5pt;font-family:'DejaVu Serif','serif';">Amazing Beijing</span></p>
<p class="MsoNormal" style="margin:0;"><span style="font-size:13.5pt;font-family:'DejaVu Serif','serif';"> </span></p>
<p class="MsoNormal" style="line-height:130%;margin:0;"><span style="font-size:13.5pt;line-height:130%;font-family:'DejaVu Serif','serif';">Despite what the detractors say, China has redeemed itself. Beijing was a tremendous, astounding success. The opening that was a panorama of colors, a touch of history and more than a pinch of drama. Thousands of athletes, hundreds of games, a little faux pas here and there, but all in all Beijing's reclaimed fame! Preparations for the games by China's athletes was rigorous and had paid off well. The Sinos got most of the gold. China is trying to prove her mettle as a responsible power, or so it seems. It is hoped that in as many other respects, such as giving what is due to its distinct peoples China might also shine some day. I rest my case, Your Honors.</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Quand compilation et exécution font la différence, un exemple]]></title>
<link>http://thesasreference.wordpress.com/?p=364</link>
<pubDate>Thu, 21 Aug 2008 06:00:58 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=364</guid>
<description><![CDATA[SAS effectue plusieurs lectures d&#8217;un programme. A la première lecture, c&#8217;est la compila]]></description>
<content:encoded><![CDATA[<p>SAS effectue plusieurs lectures d'un programme. A la première lecture, c'est la compilation. A la seconde, c'est l'exécution. Connaître ces notions vous aidera à comprendre les exemples ci-dessous : pourquoi le premier code proposé ne fonctionne pas alors que les autres passent. Les fonctions PUT, VVALUE, le dictionnaire DICTIONARY.COLUMNS et le DATA _NULL_ serviront dans les exemples.</p>
<p><strong>1. Un premier exemple avec la fonction PUT</strong></p>
<p><strong>Rappel sur la fonction PUT</strong> : Une fonction PUT permet de convertir une variable numérique en variable texte ou une variable texte en une autre variable texte. Elle est composée de deux paramètres. D'un côté, il y a la variable d'origine. De l'autre côté, il y a le format à appliquer sur cette variable d'origine. C'est donc la valeur sous forme formatée qui devient une valeur texte. Reportez vous à l'article "<a href="http://thesasreference.wordpress.com/2008/04/21/changer_type_variable/">Convertir une variable caractère en numérique et inversement</a>" pour plus de détails.</p>
<p><strong>La phase de compilation</strong> : A la compilation, SAS  vérifie que la variable d'origine et le format associé sont tous les deux du même type. Il faut qu'une variable numérique est un format qui s'applique à une variable numérique. De manière identique, il faut un format caractère pour une variable texte.</p>
<p><strong>La phase d'exécution</strong> : Si on ne connaît pas à l'avance le type de la variable, on peut avoir envie de définir une condition : si la variable est numérique applique tel format, sinon applique tel autre format. Hors une condition IF/THEN n'est visible par SAS qu'à la phase d'exécution.</p>
<p>En d'autres termes, SAS tentera d'appliquer un format numérique à une variable numérique avant de regarder si la fonction PUT est définie dans une condition.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> import_excel;<br />
   <span style="color:#0000ff;">retain</span> type <span style="color:#800080;">'CHAR'</span>;<br />
   study = <span style="color:#800080;">'999'</span>;<br />
   <span style="color:#0000ff;">output</span>;<br />
   study = <span style="color:#800080;">'888'</span>;<br />
   <span style="color:#0000ff;">output</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> study_new;<br />
   <span style="color:#0000ff;">set</span> import_excel;<br />
   <span style="color:#0000ff;">if</span> type=<span style="color:#800080;">'NUM'</span> <span style="color:#0000ff;">then</span> study_new=put(study,<span style="color:#008080;">best.</span>);<br />
   <span style="color:#0000ff;">else</span> study_new=study;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>Le résultat</strong> : Dans l'exemple, un format numérique (BEST.) est appliqué à une variable texte (STUDY). La première partie de la condition ne s'applique pas car le type de la variable n'est pas égal à NUM. Mais SAS cherche un format $BEST. qui n'existe pas. Il est obligé de s'arrêter là.</p>
<p><span style="font-family:Courier New;">28 data study_new;<br />
29 set ref;<br />
30 if upcase(type)='NUM' then study_new=put(study,best.);<br />
<span style="color:#800000;">                                                  -----<br />
                                                  48</span><br />
<span style="color:#800000;">ERROR 48-59: The format $BEST was not found or could not be loaded</span>.</span></p>
<p><span style="font-family:Courier New;">31 else study_new=study;<br />
32 run;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">NOTE: The SAS System stopped processing this step because of errors.</span><br />
<span style="color:#008000;">WARNING: The data set WORK.STUDY_NEW may be incomplete.<br />
When this step was stopped there were 0 observations and 3 variables</span>.</span></p>
<p><strong>Un exemple où le type de la variable est inconnu</strong> : en important un fichier EXCEL (PROC IMPORT/MIXED=YES), le type de la variable sous SAS peut-être inconnu. La variable sera caractère si une cellule contient du texte. Sinon, elle sera numérique.</p>
<p><strong><span style="color:#ff6600;">2. Une solution rapide</span></strong></p>
<p><strong>Une fonction Vxxx</strong>: la fonction VVALUE retourne une valeur texte. Elle utilise le format associé à la variable en interne pour construire la valeur sous forme formatée. La nouvelle variable aura une longueur de 200.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> study_new;<br />
   <span style="color:#0000ff;">set</span> ref;<br />
   <span style="color:#0000ff;">if</span> type='NUM' <span style="color:#0000ff;">then</span> study_new=vvalue(study);<br />
   <span style="color:#0000ff;">else</span> study_new=study;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="color:#ff6600;"><strong>3. Une solution plus lourde mais pouvant s'appliquer à plusieurs variables</strong></span></p>
<p>Une autre solution est de générer le code à exécuter. Si la variable est numérique, c'est l'instruction avec PUT qui apparaîtra, sinon c'est l'autre instruction. Cette approche fait appel à la notion de dictionnaire et de DATA _NULL_.</p>
<p><strong>3.1 Créer un data set contenant le nom des variables et leur type à partir du dictionnaire (<em>dictionary)</em> appelé COLUMNS</strong></p>
<p>La première étape consiste à créer un data set, nommé DICT_REF, contenant la variable STUDY et son type.</p>
<p><strong>Choix du dictionnaire</strong> : Le dictionnaire (<em>dictionary</em>) COLUMNS est un data set de référence, créé de manière automatique par SAS. Il répertorie toutes les variables contenues dans tous les data sets de toutes les bibliothèques actives. Il contient donc une ligne par variable.</p>
<p>Chaque ligne du dictionnaire contient plusieurs informations caractérisant cette variable dont :</p>
<ul>
<li>la bibliothèque d'origine (variable LIBNAME)</li>
<li>le data set d'origine (variable MEMNAME)</li>
<li>le nom de la variable (variable NAME)</li>
<li>le type de la variable (variable TYPE).</li>
</ul>
<p><strong>Prendre un sous-ensemble du dictionnaire</strong> : Ici seule la variable STUDY est utile. Elle provient du data set EXCEL_IMPORT sauvegardé de manière temporaire dans la bibliothèque WORK.</p>
<p><strong>Mettre en majuscule</strong> : Le type de la variable est soit "num" soit "char", toujours en minuscule. Le nom de la variable peut avoir un mélange de majuscules et minuscules selon la manière dont est saisi le nom lors de sa création. Pour éviter des surprises, le nom de la variable et le type sont mis en majuscule grâce à la fonction UPCASE. L'avantage des dictionnaires, c'est qu'ils peuvent lister plus d'une variable.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">create table </span>dict_ref <span style="color:#0000ff;">as</span><br />
      <span style="color:#0000ff;">select</span> upcase(name) <span style="color:#0000ff;">as</span> name,<br />
             upcase(type) <span style="color:#0000ff;">as</span> type<br />
      <span style="color:#0000ff;">from</span> dictionary.columns<br />
      <span style="color:#0000ff;">where</span> upcase(<span style="color:#0000ff;">libname</span>) = <span style="color:#800080;">'WORK'</span> <span style="color:#0000ff;">and<br />
</span>            upcase(memname) = <span style="color:#800080;">'EXCEL_IMPORT'</span> <span style="color:#0000ff;">and</span><br />
            upcase(name)    = <span style="color:#800080;">'STUDY'</span>;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p><strong>3.2 Ecrire le code et l'appeler</strong></p>
<p>La deuxième étape consiste à créer un programme nommé TMP_STUD.SAS donc le nom et l'emplacement est défini dans l'instruction FILENAME. Pour écrire dans ce fichier, l'instruction FILE est ajoutée dans le DATA _NULL_. Pour plus de précisions sur l'instruction PUT, reportez-vous à l'article "<a href="http://thesasreference.wordpress.com/2008/02/24/ecrire-un-texte-avec-linstruction-put/">Ecrire un texte avec l'instruction PUT</a>".</p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">filename</span> stud <span style="color:#800080;">'C:/sasref/tmp_stud.sas'</span>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">data</span> _null_;<br />
   <span style="color:#0000ff;">set</span> dict_ref;<br />
   <span style="color:#0000ff;">file</span> stud;<br />
<span style="color:#0000ff;">   put</span> <span style="color:#800080;">'data study_new;'</span>;<br />
   <span style="color:#0000ff;">put</span> @<strong><span style="color:#008080;">3</span></strong> <span style="color:#800080;">'set excel_import;'</span>;<br />
</span><span style="font-family:Courier New;">   <span style="color:#0000ff;">if</span> type=<span style="color:#800080;">'NUM'</span> <span style="color:#0000ff;">then put </span>@<span style="color:#008080;"><strong>3</strong></span> <span style="color:#800080;">'study_new=put('</span> name <span style="color:#800080;">',9.);'</span>;<br />
   <span style="color:#0000ff;">else put </span>@<strong><span style="color:#008080;">3</span></strong> <span style="color:#800080;">'study_new='</span> name <span style="color:#800080;">';'</span>;<br />
</span><span style="font-family:Courier New;">   <span style="color:#0000ff;">put</span> <span style="color:#800080;">'run;'</span>;<br />
<span style="color:#0000ff;">run</span>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">%include</span> stud;<br />
<span style="color:#0000ff;">filename</span> stud;</span></p>
<p>L'écriture du programme est fonction des informations contenues dans le DICT_REF. Si plus d'une variable est sélectionnée, il faudrait préciser deux choses :</p>
<ul>
<li>Les instructions DATA et SET ne sont à écrire qu'une fois. Elles sont ajoutées lors de la première boucle fait en interne autour de l'étape DATA via "if _N_=1".</li>
<li>L'instruction RUN apparaît une fois en fin de programme. Il faut donc l'ajouter une fois le dernier record du fichier de référence atteint. L'option END= de l'instruction SET crée une variable interne prenant la valeur 0 pour tous les records sauf le dernier où elle prend la valeur 1. La condition est donc basée sur cette variable.</li>
</ul>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">filename</span> stud <span style="color:#800080;">'C:/sasref/tmp_stud.sas'</span>;</span></p>
<p><span style="font-family:Courier New;"><span><span style="color:#0000ff;">data</span> _null_;<br />
   <span style="color:#0000ff;">set</span> dict_ref end=eof;<br />
   <span style="color:#0000ff;">file</span> stud;<br />
   <span style="color:#0000ff;">if</span> _N_=<strong><span style="color:#008080;">1</span></strong> <span style="color:#0000ff;">the</span>n<br />
      <span style="color:#0000ff;">do</span>;<br />
<span style="color:#0000ff;">         put</span> <span style="color:#800080;">'data study_new;'</span>;<br />
         <span style="color:#0000ff;">put</span> @<strong><span style="color:#008080;">3</span></strong> <span style="color:#800080;">'set excel_import;'</span>;<br />
</span>      <span style="color:#0000ff;">end</span>;</span><br />
<span style="font-family:Courier New;">   <span style="color:#0000ff;">if</span> type=<span style="color:#800080;">'NUM'</span> <span style="color:#0000ff;">then put </span>@<span style="color:#008080;"><strong>3</strong></span> <span style="color:#800080;">'study_new=put('</span> name <span style="color:#800080;">',9.);'</span>;<br />
   <span style="color:#0000ff;">else put </span>@<strong><span style="color:#008080;">3</span></strong> <span style="color:#800080;">'study_new='</span> name <span style="color:#800080;">';'</span>;<br />
  <span style="color:#0000ff;"> if </span>eof <span style="color:#0000ff;">then</span></span><span style="font-family:Courier New;"> <span style="color:#0000ff;">put</span> <span style="color:#800080;">'run;'</span>;<br />
<span style="color:#0000ff;">run</span>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">%include</span> stud;<br />
<span style="color:#0000ff;">filename</span> stud;</span></p>
<p>Le code sauvegardé dans le fichier TMP_STUD.SAS se présente donc ainsi, vu que la variable STUDY est de type caractère.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> study_new;<br />
   <span style="color:#0000ff;">set</span> excel_import;<br />
   study_new=STUDY ;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>L'instruction %INCLUDE permet l'exécution de ce code.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Répéter une action sur plusieurs variables avec le langage macro]]></title>
<link>http://thesasreference.wordpress.com/?p=326</link>
<pubDate>Wed, 13 Aug 2008 06:00:53 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=326</guid>
<description><![CDATA[
Sous SAS, deux possibilités sont envisageables pour répéter une action sur plusieurs variables. ]]></description>
<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-401" src="http://thesasreference.wordpress.com/files/2008/08/boucle_fr.jpg" alt="" width="448" height="224" /></p>
<p>Sous SAS, deux possibilités sont envisageables pour répéter une action sur plusieurs variables. Dans le cas d'un data step, la syntaxe de l'ARRAY est tout à fait appropriée. Dans d'autres cas, le langage macro peut s'avérer plus pertinent. Voici donc une présentation de l'approche via le langage macro.</p>
<p><strong><span style="color:#ff6600;">1. L'exemple</span></strong></p>
<p>Pour illustrer le propos, le programme aura pour but de définir un PROC REPORT contenant toutes les variables du data set SASHELP.CLASS. Si on connaît le nom des variables, la syntaxe se résume de la manière suivante.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc report</strong></span> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
   <span style="color:#0000ff;">columns</span> name age sex weight height;<br />
   <span style="color:#0000ff;">define</span> name   / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define</span> age    / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define </span>sex    / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define </span>weight / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define </span>height /<span style="color:#0000ff;"> display</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>Mais si on ne connaît pas le nom des variables par avance, il faut automatiser la tâche.</p>
<p><strong><span style="color:#ff6600;">2. Remplacer le nom des variables par des macros variables</span></strong></p>
<p>Dans l'exemple suivant, le nom de chaque variable est sauvegardé dans une macro variable. Ces macros variables ont une structure particulière :</p>
<p style="padding-left:30px;"><strong>un préfixe commun + un nombre</strong></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">%let</span> class1 = name;<br />
<span style="color:#0000ff;">%let</span> class2 = age;<br />
<span style="color:#0000ff;">%let</span> class3 = sex;<br />
<span style="color:#0000ff;">%let</span> class4 = weight;<br />
<span style="color:#0000ff;">%let</span> class5 = height;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc report</strong></span> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
   <span style="color:#0000ff;">columns</span> name age sex weight height;<br />
   <span style="color:#0000ff;">define</span> &#38;<span style="color:#008080;">class1.</span> / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define</span> &#38;<span style="color:#008080;">class2.</span> / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define</span> &#38;<span style="color:#008080;">class3.</span> / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define</span> &#38;<span style="color:#008080;">class4.</span> / <span style="color:#0000ff;">display</span>;<br />
   <span style="color:#0000ff;">define</span> &#38;<span style="color:#008080;">class5.</span> / <span style="color:#0000ff;">display</span>;<br />
<span style="color:#000080;"><strong>run</strong></span>;</span></p>
<p><strong><span style="color:#ff6600;">3. Répéter l'instruction DEFINE grâce à une boucle</span></strong></p>
<p>Grâce à cette structure particulière, une boucle peut être envisagée. L'instruction DEFINE est alors répétée autant de fois qu'il y a de variables. La boucle est définie par une macro variable "I" qui prend des valeurs allant de 1 à 5. La partie nombre de la macro variable est donc remplacée par la valeur de la macro variable "I".</p>
<p><strong>NOTE </strong>: Pour résoudre la macro variable lors de la première boucle, SAS effectue deux lectures. A la première lecture, les deux perluètes (<em>ampersand</em>) &#38;&#38; se transforment en un seul ; &#38;i. se transforme en 1. On a donc &#38;CLASS1. A la deuxième lecture, SAS résout la macro variable &#38;CLASS1. comme précédemment.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">%macro</span></strong> <strong><em>test</em></strong>;<br />
   proc report data=sashelp.class;<br />
   columns name age sex weight height;<br />
   <span style="color:#0000ff;">%do</span> i=<strong><span style="color:#008080;">1</span></strong> <span style="color:#0000ff;">%to </span><strong><span style="color:#008080;">5<br />
</span></strong>      define &#38;&#38;class&#38;<span style="color:#008080;">i.</span> / display;<br />
  <span style="color:#0000ff;"> %end</span>;<br />
   run;<br />
<strong><span style="color:#000080;">%mend</span></strong> test;<br />
<em><strong>%test</strong></em>;</span></p>
<p><strong><span style="color:#ff6600;">4. Créer les macros variables de manière automatique</span></strong></p>
<p>Pour créer les macros variables automatiquement, il faut agir en deux étapes.</p>
<ol>
<li>Enregistrer chacune des noms de variables du data set choisi dans PROC REPORT (SASHELP.CLASS) dans un nouveau data set (LST_VAR) et plus particulière dans une variable (NAME).</li>
<li>Associer un numéro à chaque nom de variable (compteur) et convertir l'information en macro variable (CALL SYMPUT).</li>
</ol>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">create</span> <span style="color:#0000ff;">table</span> lst_var <span style="color:#0000ff;">as</span><br />
      <span style="color:#0000ff;">select</span> name<br />
      <span style="color:#0000ff;">from</span> dictionary.columns<br />
      <span style="color:#0000ff;">where</span> upcase(<span style="color:#0000ff;">libname</span>)=<span style="color:#800080;">'SASHELP'</span> <span style="color:#0000ff;">and<br />
</span>            upcase(memname)=<span style="color:#800080;">'CLASS'</span>;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>data</strong></span> <span style="color:#0000ff;">_null_</span>;<br />
   <span style="color:#0000ff;">set</span> lst_var;<br />
   cnt+<span style="color:#008080;"><strong>1</strong></span>;<br />
   <span style="color:#0000ff;">call</span> symput (cats(<span style="color:#800080;">'CLASS'</span>,put(cnt,<span style="color:#008080;">best.</span>)),name);<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong><span style="color:#ff6600;">5. Compter le nombre de variables de manière automatique</span></strong></p>
<p>Si le nombre de variable dans le data set n'est pas connu à l'avance, il faut le retrouver. Cette information est ensuite sauvegardée dans une macro variable, disons MAX_VAR, et remplacera notre nombre 5. L'article "<a href="http://thesasreference.wordpress.com/2008/02/07/creer_macro_variable/">3 méthodes pour construire des macro variables sans macro</a>" vous donnera plus de précisions concernant la création d'une macro variable.</p>
<p><strong>Obtenir rapidement le nombre de variables dans un data set</strong> : Un moyen pour trouver le nombre de variables est de faire appel au dictionnaire de SAS intitulé TABLES.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc sql <span style="color:#0000ff;">noprint</span></strong></span>;<br />
   <span style="color:#0000ff;">select</span> nvar<span style="color:#0000ff;"> into </span>: max_var<br />
   <span style="color:#0000ff;">from</span> dictionary.tables<br />
   <span style="color:#0000ff;">where</span> upcase(libname)=<span style="color:#800080;">'SASHELP'</span> <span style="color:#0000ff;">and</span><br />
         upcase(memname)=<span style="color:#800080;">'CLASS'</span>;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p><strong>Plus de flexibilité sur la liste des variables concernées</strong> : Un autre moyen pour compter le nombre de variables est d'agir en deux étapes.</p>
<ul>
<li>Enregistrer dans un variable d'un nouveau data set chacune des noms de variables de SASHELP.CLASS.</li>
<li>Compter le nombre d'observations dans ce data set. Vous pouvez vous reporter à l'article "<a href="http://thesasreference.wordpress.com/2008/04/14/compter_obs/">Combien d'observations dans mon data set</a>" pour plus de précisions sur les différentes alternatives.</li>
</ul>
<p>Dans notre exemple, il s'agit de créer le data set LST_VAR pour la première étape. Le code de la section 4 est tout à fait suffisant pour cela. Ensuite, CALL SYMPUTX peut servir à sauvegarder l'information dans une macro variable.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> <span style="color:#0000ff;">_null_</span> ;<br />
   call symputx(<span style="color:#800080;">'max_var'</span>,_N_-<span style="color:#008080;"><strong>1</strong></span>);<br />
   <span style="color:#0000ff;">set</span> lst_var;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>Pourquoi vous ai-je proposé cette alternative ?</strong>  Ici, toutes les variables sont sélectionnées. Mais si seulement quelques une sont choisies, seule la seconde alternative marche. Voici quelques sous-sélections possibles.</p>
<ul>
<li>Sélectionner toutes les variables numériques,</li>
<li>Sélectionner toutes les variables finissant pas _X,</li>
<li>etc.</li>
</ul>
<p><strong><span style="color:#ff6600;">En résumé</span></strong> : En résumé, le code se décompose en 2 étapes : créer les macros variables et utiliser ces macros variables pour définir une boucle.</p>
<p><span style="color:#008000;font-family:Courier New;">*1. Créer les macros variables CLASS1 à CLASS5, MAX_VAR.;</span></p>
<p><span style="color:#008000;font-family:Courier New;">*1.1 Créer le data set LST_VAR servant de fichier de référence.;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
<span style="color:#0000ff;">   create</span> <span style="color:#0000ff;">table</span> lst_var <span style="color:#0000ff;">as</span><br />
<span style="color:#0000ff;">      select</span> name<br />
<span style="color:#0000ff;">      from</span> dictionary.columns<br />
<span style="color:#0000ff;">      where</span> upcase(<span style="color:#0000ff;">libname</span>)=<span style="color:#800080;">'SASHELP'</span> <span style="color:#0000ff;">and<br />
</span>            upcase(memname)=<span style="color:#800080;">'CLASS'</span>;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p><span style="color:#008000;font-family:Courier New;">*1.2 Créer les macro variables CLASS1-CLASS5 en se basant sur le data set LST_VAR créé précédemment.;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>data</strong></span> <span style="color:#0000ff;">_null_</span>;<br />
<span style="color:#0000ff;">   set</span> lst_var;<br />
   cnt+<span style="color:#008080;"><strong>1</strong></span>;<br />
<span style="color:#0000ff;">   call</span> symput (cats(<span style="color:#800080;">'CLASS'</span>,put(cnt,<span style="color:#008080;">best.</span>)),name);<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="color:#008000;font-family:Courier New;">*1.3 Créer la macro variable VAR_MAX en se basant sur le data set LST_VAR créé précédemment.;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> <span style="color:#0000ff;">_null_</span> ;<br />
   call symputx(<span style="color:#800080;">'max_var'</span>,_N_-<span style="color:#008080;"><strong>1</strong></span>);<br />
<span style="color:#0000ff;">   set</span> lst_var;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="color:#008000;font-family:Courier New;">*2. Reporting : appeler les différentes macro variables pour créer la boucle autour de l'instruction DEFINE.;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">%macro</span></strong> <strong><em>test</em></strong>;<br />
proc report data=sashelp.class;<br />
   columns name age sex weight height;<br />
<span style="color:#0000ff;">   %do</span> i=<strong><span style="color:#008080;">1</span></strong> <span style="color:#0000ff;">%to <span style="color:#000000;">&#38;</span></span><span style="color:#008080;"><strong>max_var.</strong><span style="color:#000000;">;</span><br />
</span>      define &#38;&#38;class&#38;<span style="color:#008080;">i.</span> / display;<br />
<span style="color:#0000ff;">   %end</span>;<br />
run;<br />
<strong><span style="color:#000080;">%mend</span></strong> test;<br />
<em><strong>%test</strong></em>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Diriger les sorties d'un PROC MEANS dans un dataset SAS]]></title>
<link>http://thesasreference.wordpress.com/?p=228</link>
<pubDate>Thu, 24 Jul 2008 06:00:12 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=228</guid>
<description><![CDATA[Par défaut, les résultats des procédures SAS sont affichés dans la fenêtre OUTPUT. Pour convert]]></description>
<content:encoded><![CDATA[<p>Par défaut, les résultats des procédures SAS sont affichés dans la fenêtre OUTPUT. Pour convertir ces résultats en tableau SAS (SAS dataset), la syntaxe de l'ODS (Output Delivery System) dispose d'outils appropriés comme les instructions </p>
<ul>
<li>ODS TRACE pour identifier une sortie,</li>
<li>ODS OUTPUT pour rediriger une sortie vers un data set,</li>
<li>ODS SELECT and ODS EXCLUDE pour choisir les sorties apparaissant dans la fenêtre OUTPUT.</li>
</ul>
<p>Pour illustrer ce sujet, la procédure PROC MEANS sera utilisée.</p>
<p><strong>Remise dans le contexte</strong> :</p>
<ul>
<li><strong>Changer l'éditeur pour une présentation plus fine </strong>: rediriger vers un document RTF avec ODS RTF s'applique une fois que la formulation nous convient.</li>
<li><strong>Changer la formulation des informations</strong> : le TEMPLATE peut préalablement être modifié pour n'afficher qu'un sous ensemble du résultat par exemple.</li>
<li><strong>Faire de gros travaux</strong> : pivoter un tableau, combiner des résultats entre eux ou encore calculer une valeur à partir des résultats existant fait partie des gros travaux qui nécessitent de passer par un dataset SAS.</li>
</ul>
<p><strong><span style="color:#ff6600;">1. Identifier le nom des résultats</span></strong></p>
<p>Pour voir le nom des différentes outputs, entourez votre procédure des instructions ODS TRACE ON/LISTING et ODS TRACE OFF.</p>
<ul>
<li>La première instruction demande l'affichage de chacune des noms des sorties.</li>
<li>L'option LISTING permet d'afficher cette information dans la fenêtre OUTPUT. La destination par défaut est la LOG.</li>
<li>Enfin, la seconde instruction désactive le traçage.</li>
</ul>
<p><strong>Premier exemple</strong></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">ods trace on</span>/<span style="color:#0000ff;">listing</span>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#008000;">*Exemple 1 : Proc Means;<br />
</span><strong><span style="color:#000080;">proc means</span></strong> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
<span style="color:#0000ff;">   var</span> height weight;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">ods trace off</span>;</span></p>
<p>On obtient la sortie de PROC MEANS appelée SUMMARY.</p>
<p><span style="font-family:Courier New;">Output Added:<br />
-------------<br />
Name: Summary<br />
Label: Summary statistics<br />
Template: base.summary<br />
Path: Means.Summary<br />
-------------</span></p>
<p><strong>Second exemple avec une instruction BY</strong> : il est toujours possible d'ajouter une instruction BY dans PROC MEANS.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc sort</strong></span> <span style="color:#0000ff;">data</span>=sashelp.class <span style="color:#0000ff;">out</span>=class;<br />
   <span style="color:#0000ff;">by</span> sex;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">ods trace on</span>/<span style="color:#0000ff;">listing</span>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#008000;">*Exemple 2 : Proc MEANS et l'instruction BY;</span><br />
<strong><span style="color:#000080;">proc means</span></strong> <span style="color:#0000ff;">data</span>=class;<br />
   <span style="color:#0000ff;">by</span> sex;<br />
   <span style="color:#0000ff;">var</span> height weight;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#0000ff;">ods trace off</span>;</span></p>
<p>Il y a plusieurs outputs pour une seule procédure. Les deux sorties ont le même nom (NAME) mais le chemin d'accès (PATH) est différent. On parle de BYGROUP1 et BYGROUP2 pour les distinguer.</p>
<p><span style="font-family:Courier New;">Output Added:<br />
-------------<br />
Name: Summary<br />
Label: Summary statistics<br />
Template: base.summary<br />
Path: Means.ByGroup1.Summary<br />
-------------</span></p>
<p><span style="font-family:Courier New;">Output Added:<br />
-------------<br />
Name: Summary<br />
Label: Summary statistics<br />
Template: base.summary<br />
Path: Means.ByGroup2.Summary<br />
-------------</span></p>
<p><strong><span style="color:#ff6600;">2. ODS OUTPUT et PROC MEANS</span></strong></p>
<p>Dans le premier exemple, un data set EXEMPLE1 est créé à partir de la sortie ONEWAYFREQ de la PROC MEANS appliquée au fichier SASHELP.CLASS.</p>
<p>J'ai choisi d'écrire l'instruction ODS OUTPUT à l'intérieur de la procédure puisqu'elle s'applique uniquement à la procédure mais elle peut être aussi affichée avant la procédure.</p>
<p><strong>Une seule instruction pour plusieurs data sets à créer</strong> : Ecrire l'instruction ODS OUTPUT avant la procédure est intéressant si vous générez plusieurs sorties de procédures différentes et voulez lister tous les data sets SAS à créer en une seul instruction ODS OUTPUT.</p>
<p><span style="font-family:Courier New;"><span style="color:#008000;">*Exemple 1 : Proc Means;<br />
</span><strong><span style="color:#000080;">proc means</span></strong> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
<span style="color:#0000ff;">   var</span> height weight;<br />
   <span style="color:#0000ff;">ods output</span> summary=exemple1;<br />
<strong><span style="color:#000080;">run</span></strong>;</span><br />
 <br />
<strong>Un fichier brut peu lisible</strong> : Après un PROC PRINT sur le data set EXEMPLE1, on découvre un fichier peu lisible dès qu'il y a plus d'une variable.</p>
<p><span style="font-family:Courier New;">   VName_          <br />
   Height      Height_N    Height_Mean   </span><br />
<span style="font-family:Courier New;">   Height        19        62.336842105   </span></p>
<p><span style="font-family:Courier New;">   Height_<br />
   StdDev      Height_Min  Height_Max</span><br />
<span style="font-family:Courier New;">5.1270752466     51.3          72</span></p>
<p><span style="font-family:Courier New;">   VName_<br />
   Weight      Weight_N    Weight_Mean<br />
   Weight        19        100.02631579 </span></p>
<p><span style="font-family:Courier New;">  Weight_<br />
   StdDev      Height_Min  Height_Max<br />
22.773933494     50.5          150</span></p>
<p><strong>Solution, étape 1</strong> : Une solution est de faire un PROC TRANSPOSE pour un résultat sous la forme ci-dessous.</p>
<p><span style="font-family:Courier New;">   _NAME_     _LABEL_     COL1</span></p>
<p><span style="font-family:Courier New;">Height_N      N          19.000<br />
Height_Mean   Mean       62.337<br />
Height_StdDev Std Dev     5.127<br />
Height_Min    Minimum    51.300<br />
Height_Max    Maximum    72.000<br />
Weight_N      N          19.000<br />
Weight_Mean   Mean      100.026<br />
Weight_StdDev Std Dev    22.774<br />
Weight_Min    Minimum    50.500<br />
Weight_Max    Maximum   150.000</span></p>
<p>Dans la sortie brute de l'ODS OUTPUT, les variables commencent soit par HEIGHT, soit par WEIGHT (soit par VNAME ne m'intéresse pas ici). Il s'agit de transposer toutes ces variables. Il faut donc toutes les lister. Par soucis de clarté et de simplicité, on peut faire appel à une version abrégée : la racine commune des variables suivie de deux points.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> <span style="color:#0000ff;">data</span>=exemple1 <span style="color:#0000ff;">out</span>=exemple1;<br />
   <span style="color:#0000ff;">var </span>height: weight:;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>Solution, étape 2 </strong>: Pour retrouver une présentation semblable à celle d'un PROC MEANS envoyé dans la fenêtre OUTPUT, il faut transposer de nouveau. Auparavant, il faut créer une variable distinguant la variable HEIGHT de la variable WEIGHT.</p>
<p><span style="font-family:Courier New;">var_name  N   Mean   Std_Dev Minimum Maximum</span></p>
<p><span style="font-family:Courier New;"> Height  19  62.337  5.1271    51.3     72<br />
 Weight  19 100.026 22.7739    50.5    150</span></p>
<p>Créer une variable nommée VAR_NAME prenant soit la valeur HEIGHT soit la valeur WEIGHT.</p>
<ul>
<li>La fonction SCAN récupérera, dans une variable nommée VAR_NAME, le premier mot de la variable _NAME_ après avoir précisé que chaque mot est séparé par un trait bas (<em>underscore</em>).</li>
<li>La longueur de la variable est définie explicitement au cas où certains noms de variables seraient supérieurs à 8 et donc tronqués.</li>
<li>Cette longueur est définie avant l'instruction SET pour que la variable VAR_NAME apparaisse en premier.</li>
</ul>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> exemple1 (drop=_name_);<br />
   <span style="color:#0000ff;">length</span> var_name $<strong><span style="color:#008080;">12</span></strong>;<br />
   <span style="color:#0000ff;">set</span> exemple1;<br />
   var_name=scan(_name_,<strong><span style="color:#008080;">1</span></strong>,<span style="color:#800080;">'_'</span>);<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>Il est alors possible de faire pivoter le data set. Une ligne est créée pour HEIGHT et une autre pour WEIGHT, c'est-à-dire pour chaque nouvelle valeur de VAR_NAME. Chaque colonne prend le nom contenu dans la variable _LABEL_.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc transpose </strong></span><span style="color:#0000ff;">data</span>=exemple1 <span style="color:#0000ff;">out</span>=exemple1 (drop=_name_);<br />
   <span style="color:#0000ff;">by</span> var_name;<br />
   <span style="color:#0000ff;">id</span> _label_;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>L'instruction BY</strong> : Dans le cas du PROC MEANS, on ne rencontre pas de difficulté particulière liée à l'instruction BY. Au lieu d'avoir une ligne dans le fichier de sortie, on a autant de lignes que de valeurs dans la variable de l'instruction BY. Dans notre exemple, on a donc deux lignes avec une instruction BY SEX. Vous pouvez retrouver le code pour la transposition en fin d'article pour obtenir la sortie suivante :</p>
<p><span style="font-family:Courier New;">Sex=F</span></p>
<p><span style="font-family:Courier New;">var_name  N   Mean  Std_Dev Minimum Maximum</span></p>
<p><span style="font-family:Courier New;"> Height   9 60.5889  5.0183   51.3    66.5<br />
 Weight   9 90.1111 19.3839   50.5   112.5</span></p>
<p><span style="font-family:Courier New;">Sex=M</span></p>
<p><span style="font-family:Courier New;">var_name  N  Mean  Std_Dev Minimum Maximum</span></p>
<p><span style="font-family:Courier New;"> Height  10  63.91  4.9379    57.3    72<br />
 Weight  10 108.95 22.7272    83.0   150</span></p>
<p><strong><span style="color:#ff6600;">3. Sélectionner ou exclure certaines sorties ou toute les sorties (ODS EXCLUDE, SELECT, LISTING)</span></strong></p>
<p>L'instruction ODS LISTING CLOSE suspend l'envoie de toutes les sorties dans la fenêtre OUTPUT. L'ODS EXCLUDE interrompt un sous-ensemble ou toutes les sorties générées par la procédure. A l'inverse, l'ODS SELECT retient les sorties. A vous de voir si vous avez plus vite fait de lister les sorties à garder ou celles à exclure.</p>
<p><strong>Quelques sorties</strong> : Pour sélectionner ou exclure quelques sorties en particulier, il suffit d'ajouter leur nom, trouvés au préalable avec ODS TRACE ON, séparé par un espace dans l'instruction. Cela est pratique pour des procédures générant beaucoup de sorties comme PROC UNIVARIATE. </p>
<p><strong>Toutes les sorties</strong> : Pour faire la même chose sur toutes les sorties, on utilise ALL et NONE avec ODS EXCLUDE et ODS SELECT.</p>
<p><span style="font-family:Courier New;"><span style="color:#008000;">*Exemple 1 : Proc Means;<br />
</span><br />
<span style="color:#0000ff;">ods exclude all</span><strong>; <span style="color:#008000;">*ods select none; *ods listing close;<br />
</span><span style="color:#000080;">proc means</span></strong> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
<span style="color:#0000ff;">   var</span> height weight;</span><span style="font-family:Courier New;"><br />
   <span style="color:#0000ff;">ods output</span> summary=exemple1;<br />
<strong><span style="color:#000080;">run</span></strong>;<br />
<span style="color:#0000ff;">ods exclude none</span>; <span style="color:#008000;">*ods select all; *ods listing;</span></span></p>
<p><strong>Note</strong> : Toutes les explications couvertes dans cet article s'appliquent aussi à la procédure PROC SUMMARY.</p>
<p><strong><span style="color:#ff6600;">Annexe </span></strong>: Détails du programme s'appliquant au second exemple</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><span style="color:#008000;">*Exemple 2 : Proc MEANS et l'instruction BY;</span></span></span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc sort</strong></span> <span style="color:#0000ff;">data</span>=sashelp.class <span style="color:#0000ff;">out</span>=class;<br />
   <span style="color:#0000ff;">by</span> sex;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc means</strong></span><span style="color:#0000ff;"> data</span>=class;<br />
   <span style="color:#0000ff;">by</span> sex;<br />
   <span style="color:#0000ff;">var</span> height weight;<br />
   <span style="color:#0000ff;">ods output </span>summary=exemple2;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> <span style="color:#0000ff;">data</span>=exemple2 <span style="color:#0000ff;">out</span>=exemple2;<br />
   <span style="color:#0000ff;">by</span> sex;<br />
   <span style="color:#0000ff;">var</span> height: weight:;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> exemple2 (drop=_name_);<br />
   <span style="color:#0000ff;">length</span> var_name $<strong><span style="color:#008080;">12</span></strong>;<br />
   <span style="color:#0000ff;">set</span> exemple2;<br />
   var_name=scan(_name_,<strong><span style="color:#008080;">1</span></strong>,<span style="color:#800080;">'_'</span>);<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> <span style="color:#0000ff;">data</span>=exemple2 <span style="color:#0000ff;">out</span>=exemple2 (drop=_name_);<br />
   <span style="color:#0000ff;">by</span> sex var_name;<br />
   <span style="color:#0000ff;">id</span> _label_;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc print</strong> </span><span style="color:#0000ff;">data</span>=exemple2<span style="color:#0000ff;"> noobs</span>;<br />
   <span style="color:#0000ff;">by</span> sex;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[2 suggestions pour grouper les valeurs d'une variable]]></title>
<link>http://thesasreference.wordpress.com/?p=214</link>
<pubDate>Mon, 21 Jul 2008 06:00:32 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=214</guid>
<description><![CDATA[Sous SAS, lorsqu&#8217;une variable contient plusieurs valeurs à regrouper pour n&#8217;en former q]]></description>
<content:encoded><![CDATA[<p>Sous SAS, lorsqu'une variable contient plusieurs valeurs à regrouper pour n'en former qu'une seule, il existe plusieurs options. Voici deux suggestions : une basée sur la notion de RETAIN et FIRST/LAST, l'autre sur PROC TRANSPOSE et ARRAY.</p>
<p>Pour illustrer le propos un data set liste plusieurs actions pour un patient à une visite donnée. Il s'agit de regrouper ces actions par patient et visite dans un seul record.</p>
<p><strong>Le data set avant</strong></p>
<p><span style="font-family:Courier New;">pat_id  visit_dt rec_id action</span></p>
<p><span style="font-family:Courier New;">   1   02APR2007    1   RAYON X<br />
   1   02APR2007    2   ULTRASON<br />
   1   02APR2007    3   SCANNER<br />
   2   15NOV2007    2   RAYON X<br />
   2   15NOV2007    1   ULTRASON</span></p>
<p><strong>Le data set après :</strong> une nouvelle variable caractère est créée ACTION_LST. On lui donnera une longueur de 200. Chaque action y est séparée par une barre. Les variables REC_ID (identifiant du record) et ACTION sont supprimées.</p>
<p><span style="font-family:Courier New;">pat_id  visit_dt action_lst</span></p>
<p><span style="font-family:Courier New;">   1   02APR2007 RAYON X &#124; ULTRASON &#124; SCANNER<br />
   2   15NOV2007 ULTRASON &#124; RAYON X</span></p>
<p><strong><span style="color:#ff6600;">1. La force du RETAIN</span></strong></p>
<p>Pour débuter une variable ACTION_LST de longueur 200 est créée. Elle ne contient à la base aucune valeur.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> final; <span style="color:#008000;">*(drop = rec_id action);<br />
</span>   <span style="color:#0000ff;">set</span> orig;<br />
   <span style="color:#0000ff;">by</span> pat_id visit_dt;<br />
   <span style="color:#0000ff;">length</span> action_lst $<strong><span style="color:#008080;">200</span></strong>;<br />
   <span style="color:#0000ff;">retain</span> action_lst ' ';<br />
   <span style="color:#0000ff;">if</span> first.visit_dt <span style="color:#0000ff;">then</span> action_lst=action;<br />
   <span style="color:#0000ff;">else</span> action_lst=catx(<span style="color:#800080;">' &#124; '</span>,action_lst,action);<br />
   <span style="color:#008000;">*if last.visit_dt then output;<br />
</span><strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>Pour chaque nouvelle visite de chaque patient, ACTION_LST est initialisée. Elle prend la valeur de la variable ACTION.</p>
<p>Du fait de la présence de l'instruction RETAIN, cette première valeur est maintenue pour tous les records d'une même visite. A chaque nouvelle lecture d'un record, une nouvelle action est ajoutée.</p>
<p>La fonction CATX permet de concaténer les valeurs d'ACTION_LST et ACTION, et d'ajouter la barre comme délimiteur.</p>
<p>Voici donc le résultat intermédiaire, avant l'activation du code mis en commentaires.</p>
<p><span style="font-family:Courier New;">pat_id  visit_dt action_lst</span></p>
<p><span style="font-family:Courier New;">   1   02APR2007 RAYON X<br />
   1   02APR2007 RAYON X &#124; ULTRASON<br />
   1   02APR2007 RAYON X &#124; ULTRASON &#124; SCANNER<br />
   2   15NOV2007 ULTRASON<br />
   2   15NOV2007 ULTRASON &#124; RAYON X</span></p>
<p>A présent, il s'agit de garder seulement le dernier record de chaque visite par patient avec LAST.VISIT_DT et à supprimer les variables REC_ID et ACTION.</p>
<p><strong><span style="color:#ff6600;">2. Rotation de données (PROC TRANSPOSE) et lecture en boucle (ARRAY)</span></strong></p>
<p>Avec cette seconde approche, le travail est découpé en deux étapes à commencer.</p>
<p>Dans un premier temps, un PROC TRANSPOSE pour faire pivoter les données. Le data set n'a alors plus qu'une ligne par visite de patient. Chaque action apparaît dans une colonne donnée.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> <span style="color:#0000ff;">data</span>=orig <span style="color:#0000ff;">out</span>=final2 (drop=_name_);<br />
   <span style="color:#0000ff;">by</span> pat_id visit_dt;<br />
   <span style="color:#0000ff;">var</span> action;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;">pat_id  visit_dt  COL1      COL2      COL3</span></p>
<p><span style="font-family:Courier New;">   1   02APR2007  RAYON X   ULTRASON  SCANNER<br />
   2   15NOV2007  ULTRASON  RAYON X</span></p>
<p>Dans un second temps un ARRAY nommé _ACTION est défini. Il contient toutes les variables commençant par COL. A chaque nouvelle lecture d'une variable COL, sa valeur est ajoutée à celle de la variable ACTION_LST.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> final2 (drop=i col:);<br />
   <span style="color:#0000ff;">set</span> final2;<br />
   <span style="color:#0000ff;">length </span>action_lst $<strong><span style="color:#008080;">200</span></strong>;<br />
   <span style="color:#0000ff;">array</span> _action {*} col:;<br />
   <span style="color:#0000ff;">do</span> i=<strong><span style="color:#008080;">1</span></strong> <span style="color:#0000ff;">to</span> dim(_action);<br />
      action_lst = catx(<span style="color:#800080;">' &#124; '</span>,action_lst,_action{i});<br />
   <span style="color:#0000ff;">end</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong><span style="color:#ff6600;">Annexe </span></strong>: Création du data set utilisé pour l'exemple.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> orig;<br />
   <span style="color:#0000ff;">input</span> pat_id visit_dt <span style="color:#008080;">date9.</span> rec_id action $15.;<br />
   <span style="color:#0000ff;">format</span> visit_dt <span style="color:#008080;">date9.</span>;<br />
   <span style="color:#0000ff;">datalines</span>;<br />
1 02APR2007 1 RAYON X<br />
1 02APR2007 2 ULTRASON<br />
1 02APR2007 3 SCANNER<br />
2 15NOV2007 2 RAYON X<br />
2 15NOV2007 1 ULTRASON<br />
;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sort</span></strong> <span style="color:#0000ff;">data</span>=orig;<br />
   <span style="color:#0000ff;">by</span> pat_id visit_dt;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Ruby Blocks]]></title>
<link>http://jaredtse.wordpress.com/?p=19</link>
<pubDate>Fri, 18 Jul 2008 12:00:40 +0000</pubDate>
<dc:creator>jaredtse</dc:creator>
<guid>http://jaredtse.wordpress.com/?p=19</guid>
<description><![CDATA[Creating Ruby Blocks
Blocks are really easy and very usefull part of ruby.
There are two ways of co]]></description>
<content:encoded><![CDATA[<p><strong>Creating Ruby Blocks</strong></p>
<p>Blocks are really easy and very usefull part of ruby.</p>
<p>There are two ways of constracting blocks in Ruby.  The first is to use <strong>{}</strong> and place the code between the curly braces, like this "  <strong>{ code block  }</strong>".  We use this if the code is one line long.  The second is to use the <strong>do/</strong><strong>end</strong> keywords placing the ruby code between the keywords.  This way of creating block is useful when the code is in multiple lines.  Whereas the previous, is used when the code is in a single line.</p>
<p> <strong>A Ruby method, which takes a block as argument.</strong></p>
<p>This snippet demonstrate how to pass implicitely a ruby block as a parameter of the method.  Implecitly because, I am not converting the block into a proc object (more on this later).</p>
<p>IRB certified code ;-)</p>
<p>irb(main):030:0&#62;   <strong>def name(&#38;blk)</strong><br />
irb(main):031:1&#62;     <strong>sleep 3</strong><br />
irb(main):032:1&#62;     <strong>puts "I am inside the method . . "</strong><br />
irb(main):033:1&#62;     <strong>sleep 3</strong><br />
irb(main):034:1&#62;     <strong>blk.call</strong><br />
irb(main):035:1&#62;     <strong>sleep 3</strong><br />
irb(main):036:1&#62;     <strong>puts "and back to the method"</strong><br />
irb(main):037:1&#62;     <strong>sleep 3</strong><br />
irb(main):038:1&#62;   <strong>end</strong><br />
=&#62; nil<br />
irb(main):039:0&#62;<br />
irb(main):040:0* <strong>name { puts "from the block"}</strong><br />
=&#62;  I am inside the method . .<br />
=&#62;  from the block<br />
=&#62;  and back to the method</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Identifier et supprimer les doublons]]></title>
<link>http://thesasreference.wordpress.com/?p=163</link>
<pubDate>Mon, 14 Jul 2008 06:00:38 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=163</guid>
<description><![CDATA[
Identifier et supprimer les doublons dans un data set fait partie des compétences de base du pro]]></description>
<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-164" src="http://thesasreference.wordpress.com/files/2008/06/poussins_fr.jpg" alt="" width="448" height="224" /></p>
<p>Identifier et supprimer les doublons dans un data set fait partie des compétences de base du programmeur SAS. Trois approches sont envisageables : PROC SQL, PROC SORT et un compteur dans un data step.</p>
<p><strong>Qu'appelle-t-on doublon ? des lignes complètement identiques ou seulement des lignes ayant quelques variables communes ?</strong> Il est important de savoir si deux records ayant des observations communes sont considérés comme doublons ou s'il faut que toutes les observations soient identiques. Si seules quelques variables sont considérées, il faut savoir quelle ligne est conservée et lesquelles sont supprimées.</p>
<p>Le data set utilisé pour l'exemple est composé de trois variables CNTRY (country), PAT_ID (patient ID) et VAL (value). Le patient 2 de Chine a trois lignes d'observations dont deux strictement identiques.</p>
<p><span style="font-family:Courier New;">cntry    pat_id    val</span></p>
<p><span style="font-family:Courier New;"> CN        1        A<br />
 CN        2        B<br />
 CN        2        C<br />
 CN        2        C<br />
 HK        3        E </span></p>
<p><strong><span style="color:#ff6600;">1. PROC SQL</span></strong></p>
<p>Avec la procédure SQL, il est possible de faire des calculs et de baser sa sélection d'observations sur ce calcul. En d'autres termes, il est possible de compter le nombre de fois qu'une valeur apparaît. Pour identifier les records avec doublons, on prend ceux comptés plus d'une fois.</p>
<p><strong>Première présentation</strong> : Voici, tout d'abord, une présentation de PROC SQL décomposable en deux étapes.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">create table </span>two (<span style="color:#0000ff;">where</span>=(cnt_pat &#62; <strong><span style="color:#008080;">1</span></strong>)) <span style="color:#0000ff;">as</span><br />
      <span style="color:#0000ff;">select</span> cntry, pat_id, val, count(*) <span style="color:#0000ff;">as</span> cnt_pat<br />
      <span style="color:#0000ff;">from</span> one<br />
      group <span style="color:#0000ff;">by</span> cntry, pat_id;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p>Dans un premier temps, une variable donne le nombre de records par patient dans un pays donné (CNT_PAT) grâce à la syntaxe GROUP BY et la fonction COUNT. A ce stade, on obtient le data set suivant :</p>
<p><span style="font-family:Courier New;">cntry pat_id val cnt_pat</span></p>
<p><span style="font-family:Courier New;">  CN     1    A     1<br />
  CN     2    C     3<br />
  CN     2    B     3<br />
  CN     2    C     3<br />
  HK     3    E     1</span></p>
<p>Dans un second temps, seules les observations ayant des doublons sont gardées, une fois le nouveau data set créé, grâce à l'option WHERE=.</p>
<p><strong>Deuxième présentation</strong> : Au lieu de créer la variable CNT_PAT et de faire une sélection ultérieure, la fonction COUNT peut être  ajoutée dans une condition introduite par le mot HAVING et faisant toujours appel à la fonction COUNT.</p>
<p>Pour ne voir qu'une des lignes multiples, il suffit d'ajouter DISTINCT.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">create table </span>two_bis <span style="color:#0000ff;">as</span><br />
   <span style="color:#0000ff;">select</span> <span style="color:#008000;">/*distinct*/ </span>cntry, pat_id, val<br />
   <span style="color:#0000ff;">from</span> one<br />
   group <span style="color:#0000ff;">by </span>cntry, pat_id<br />
   having count(*) &#62; <strong><span style="color:#008080;">1</span></strong>;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p>A l'inverse, pour ne sélectionner que les observations n'apparaissant qu'une fois, "&#62;1" sera remplacé par "=1". Seules les observations ayant exactement une occurrence sont sélectionnées.</p>
<p>Le DISTINCT s'applique à l'intégralité des observations. Cela permet de ne garder que des lignes uniques.</p>
<p>Il n'est pas possible de garder la première ligne parmi les doublons définis par des variables précises (CNTRY et PAT_ID dans l'exemple) avec cette méthode.</p>
<p><strong><span style="color:#ff6600;">2. Les options de la procédure PROC SORT (NODUP/NODUPRECS, NODUPKEY)</span></strong></p>
<p>Il existe deux options dans la procédure PROC SORT pour supprimer les doublons selon qu'ils s'appliquent</p>
<ul>
<li>à toute une ligne d'observation (NODUPRECS dont l'alias est NODUP) ou</li>
<li>à une liste de variables précises données dans l'instruction BY (NODUPKEY).</li>
</ul>
<p>Au choix, le nouveau data set sans doublons remplace l'ancien ou est sauvegardé dans un dataset différent introduit par OUT=.</p>
<p>Les observations ayant été exclues peuvent être sauvegardées dans un nouveau data set dont le nom est défini par DUPOUT=.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sort</span></strong> <span style="color:#0000ff;">data</span>=one<span style="color:#0000ff;"> out</span>=three nodupkey dupout=three_bis;<br />
   <span style="color:#0000ff;">by</span> cntry pat_id;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc sort</strong></span> <span style="color:#0000ff;">data</span>=one <span style="color:#0000ff;">out</span>=four noduprecs <span style="color:#008000;">/*nodup*/ </span>dupout=four_bis;<br />
   <span style="color:#0000ff;">by</span> cntry pat_id;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong><span style="color:#ff6600;">3. Appliquer une variable compteur</span></strong></p>
<p>Enfin, après PROC SQL et PROC SORT, une troisième possibilité pour identifier et supprimer les doublons, est d'ajouter une variable compteur.</p>
<p>Dans l'exemple ci-dessous, la variable compteur est nommée CNT. Pour la première observation d'un patient d'un pays donné, le compteur est initialisé à 1. Pour chaque nouveau record du patient, le compteur est incrémenté de 1. Quand la variable CNT est égale à 1, le record est ajouté dans le data set FIVE. Sinon il est ajouté dans le data set FIVE_BIS. A la fin, la variable compteur est supprimée.</p>
<p>Ainsi le data set FIVE contient les records sans doublons. Dans le cas du patient doublonné (patient 2), c'est la première observation qui est conservée.</p>
<p>Dans le data set FIVE_BIS, les records exclus de la première sélection sont conservés.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> five (drop=cnt) five_bis (drop=cnt);<br />
   <span style="color:#0000ff;">set</span> one;<br />
   <span style="color:#0000ff;">by</span> cntry pat_id val;<br />
   <span style="color:#0000ff;">if</span> first.pat_id <span style="color:#0000ff;">then</span> cnt=<span style="color:#008080;"><strong>1</strong></span>;<br />
   <span style="color:#0000ff;">else</span> cnt+<strong><span style="color:#008080;">1</span></strong>;<br />
   <span style="color:#0000ff;">if</span> cnt = <strong><span style="color:#008080;">1</span></strong> <span style="color:#0000ff;">then output</span> five;<br />
   <span style="color:#0000ff;">else output </span>five_bis;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong><span style="color:#ff6600;">Annexe :</span></strong></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> one;<br />
   <span style="color:#0000ff;">input</span> cntry $ pat_id $ val $;<br />
   <span style="color:#0000ff;">datalines</span>;<br />
CN 1 A<br />
CN 2 B<br />
CN 2 C<br />
CN 2 C<br />
HK 3 E<br />
;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Faire pivoter un data set (un 1er exemple de PROC TRANSPOSE)]]></title>
<link>http://thesasreference.wordpress.com/?p=201</link>
<pubDate>Thu, 10 Jul 2008 06:00:16 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=201</guid>
<description><![CDATA[
La transposition de jeux de données sous SAS est une étape fréquente dans le processus de progra]]></description>
<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-226" src="http://thesasreference.wordpress.com/files/2008/07/phone_fr.jpg" alt="" width="448" height="224" /></p>
<p>La transposition de jeux de données sous SAS est une étape fréquente dans le processus de programmation. Voici pour débuter un premier exemple pour se familiariser avec la syntaxe de base.</p>
<p><strong><span style="color:#ff6600;">1. Les données d'origine</span></strong></p>
<p>Le data set illustrant le sujet est composé de trois variables :</p>
<ul>
<li>le numéro du patient (PAT_ID)</li>
<li>le numéro de la visite (VISIT) prenant les valeurs 18 pour début de visite, 50 pour fin de visite et 70 pour suivi</li>
<li>la date de cette visite (VISIT_DT).</li>
</ul>
<p>En fin d'article, vous trouverez le code pour créer ce data set.</p>
<p><span style="font-family:Courier New;">pat_id visit visit_dt</span></p>
<p><span style="font-family:Courier New;">   1     18  25MAR2007<br />
   1     70  15OCT2007<br />
   1     50  01JUL2007<br />
   2     18  14APR2007<br />
   2     50  08AUG2007<br />
   3     50  16OCT2007</span></p>
<p><strong><span style="color:#ff6600;">2. Le minimum</span></strong></p>
<p>Pour afficher une ligne par patient, il faut faire appel à la procédure PROC TRANSPOSE.</p>
<p>Dans le cas présent, on a choisi d'afficher la date de la visite (VAR VISIT_DT) pour chaque patient (BY PAT_ID). Le numéro de la visite est perdu dans cette transposition.</p>
<p>Le minimum de la syntaxe requiert la création d'un nouveau data set introduit par le mot-clé OUT=. Ce data set peut avoir le même nom que le data set d'origine. Il faut au moins lister une variable.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc transpose</strong></span> <span style="color:#0000ff;">data</span>=one <span style="color:#0000ff;">out</span>=two;<br />
   <span style="color:#0000ff;">by </span>pat_id;<br />
   <span style="color:#0000ff;">var</span> visit_dt;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;">pat_id  _NAME_    COL1      COL2      COL3</span></p>
<p><span style="font-family:Courier New;">   1   visit_dt 25MAR2007 15OCT2007 01JUL2007<br />
   2   visit_dt 14APR2007 08AUG2007         .<br />
   3   visit_dt 16OCT2007         .         .</span></p>
<p><span style="color:#ff6600;"><strong>3. Les options et instructions supplémentaires</strong> </span></p>
<p><strong>3.1 Des variables automatiques supprimées avec l'option DROP= :</strong> Le nom de la variable utilisée pour créer les colonnes COL1-COL3 est donné de manière automatique par SAS. Cette information est sauvegardée dans la variable _NAME_. Elle peut dont être supprimée avec l'option DROP attachée au data set de sortie nommé TWO.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> <span style="color:#0000ff;">data</span>=one <span style="color:#0000ff;">out</span>=two (drop=_name_);<br />
   <span style="color:#0000ff;">by</span> pat_id;<br />
   <span style="color:#0000ff;">var</span> visit_dt;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;">pat_id         COL1         COL2         COL3</span></p>
<p><span style="font-family:Courier New;">   1      25MAR2007    15OCT2007    01JUL2007<br />
   2      14APR2007    08AUG2007            .<br />
   3      16OCT2007            .            .</span></p>
<p><strong>3.2 Une colonne propre à une visite donnée grâce à l'instruction ID :</strong> On remarque que pour le premier patient, la visite du 15 octobre est citée avant celle du 1er juillet. En d'autres termes, une colonne donnée ne correspond pas à une visite donnée mais à l'ordre des données dans le fichier source. De la même manière, la deuxième visite du troisième patient apparaît dans la première colonne.</p>
<p>Pour que chaque colonne corresponde à un numéro de visite donné, on fait appel à l'instruction ID suivie du nom de la variable définissant la colonne. Dans notre cas, il s'agit de la variable VISIT.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> data=one <span style="color:#0000ff;">out</span>=two (drop=_name_);<br />
   <span style="color:#0000ff;">by </span>pat_id;<br />
   <span style="color:#0000ff;">var</span> visit_dt;<br />
   <span style="color:#0000ff;">id </span>visit;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;">pat_id          _18          _70          _50</span></p>
<p><span style="font-family:Courier New;">   1      25MAR2007    15OCT2007    01JUL2007<br />
   2      14APR2007            .    08AUG2007<br />
   3              .            .    16OCT2007</span></p>
<p><strong>3.3 Des noms de colonnes personnalisés grâce à PREFIX =</strong> : Maintenant chaque colonne correspond à une visite en particulier. Comme les numéros de visites sont des nombres et que les variables de SAS ne peuvent commencer par un chiffre, SAS ajoute automatiquement un tiret bas devant. Pour donner un nom un peu plus parlant, on peut ajouter un préfixe à ces noms de colonne.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc transpose</span></strong> <span style="color:#0000ff;">data</span>=one <span style="color:#0000ff;">out</span>=two (drop=_name_) <span style="color:#0000ff;">prefix</span>=VISIT;<br />
   <span style="color:#0000ff;">by</span> pat_id;<br />
   <span style="color:#0000ff;">var</span> visit_dt;<br />
   <span style="color:#0000ff;">id</span> visit;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;">pat_id      VISIT18      VISIT70      VISIT50</span></p>
<p><span style="font-family:Courier New;">   1      25MAR2007    15OCT2007    01JUL2007<br />
   2      14APR2007            .    08AUG2007<br />
   3              .            .    16OCT2007 </span></p>
<p><strong>3.4 Lister toutes les variables commençant par un nom donné</strong></p>
<p>Avoir une série de variables commençant par le même préfixe présente des avantages car SAS permet d'y référer très simplement.</p>
<p><strong>La syntaxe SAS</strong> : Pour lister toutes ces variables, il suffit de faire suivre le préfixe de deux points. Dans notre exemple, toutes les variables commençant par le mot VISIT sont listées avec VISIT:.</p>
<p>Voici quelques exemples d'applications de cette syntaxe :</p>
<ul>
<li>un PROC TRANSPOSE : lister les variables à transposer</li>
<li>une option KEEP/DROP : lister les variables à garder ou à supprimer</li>
<li>un ARRAY : lister les variables définissant l'array.</li>
</ul>
<p><strong><span style="color:#ff6600;">Annexe </span></strong>:</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> one;<br />
   <span style="color:#0000ff;">input</span> pat_id visit visit_dt <span style="color:#008080;"><strong>date9.</strong></span>;<br />
   <span style="color:#0000ff;">format</span> visit_dt <span style="color:#008080;"><strong>date9.</strong></span>;<br />
   <span style="color:#0000ff;">datalines</span>;<br />
1 18 25MAR2007<br />
1 70 15OCT2007<br />
1 50 01JUL2007<br />
2 18 14APR2007<br />
2 50 08AUG2007<br />
3 18 16OCT2007<br />
;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Penser conditionnel (3/3) : CASE WHEN]]></title>
<link>http://thesasreference.wordpress.com/?p=195</link>
<pubDate>Thu, 03 Jul 2008 06:00:21 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=195</guid>
<description><![CDATA[
Après avoir présenté les deux alternatives sous SAS dans un data step pour définir des conditio]]></description>
<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-167" src="http://thesasreference.wordpress.com/files/2008/06/bouda_fr.jpg" alt="" width="435" height="224" /></p>
<p>Après avoir présenté les deux alternatives sous SAS dans un data step pour définir des conditions (<a title="sas condition if then else" href="http://thesasreference.wordpress.com/2008/06/19/if_then_else/">La base du IF</a> et <a title="sas condition select when" href="http://thesasreference.wordpress.com/2008/06/26/condition_select_when/">SELECT</a>), partons voir la syntaxe de PROC SQL pour définir une nouvelle variable.</p>
<p><strong><span style="color:#ff6600;">1. Différences et ressemblances avec les IF et SELECT</span></strong></p>
<p><strong>Différences </strong>: A la différence des deux syntaxes du data step,...</p>
<ul>
<li>... une seule action est possible pour une condition donnée : à savoir définir une et une seule nouvelle variable ou macro variable. Les conditions ne peuvent dont pas servir pour créer de nouveaux data sets ou imbriquer des conditions dans d'autres conditions.</li>
<li>... le nom de la nouvelle variable n'est donné qu'une seule fois.</li>
</ul>
<p><strong>Ressemblances</strong> :</p>
<ul>
<li>Comme dans SELECT WHEN et ELSE IF,  seuls les records non déjà valides pour les cas listés précédemment sont relus.</li>
<li>Comme IF THEN, une dernière condition ELSE liste tous les cas non sélectionnés auparavant.</li>
</ul>
<p>Un des avantages de la procédure SQL est de pouvoir définir une nouvelle variable à partir d'une ancienne variable portant le même nom. Alors que dans un data step, cela se passe en plusieurs étapes : </p>
<ul>
<li>Tout d'abord, la variable est renommée pour pouvoir se servir de son nom d'origine pour la nouvelle variable.</li>
<li>Ensuite la variable d'origine portant le nom créé uniquement pour l'occasion est supprimée.</li>
</ul>
<p>Un autre avantage est l'usage des fonctions et du mot-clé DISTINCT.</p>
<p><strong><span style="color:#ff6600;">2. La syntaxe CASE WHEN en exemple</span></strong></p>
<p><strong>2.1 Définir une variable à partir de plusieurs variables</strong></p>
<p>Dans cet exemple, la variable POP prend au maximum 4 valeurs :</p>
<ul>
<li>1 si la variable AGE est supérieure à 13 et la variable SEX est égale à F ;</li>
<li>2 si l'AGE est entre 0 et 13 et qu'il s'agit d'une femme ;</li>
<li>3 si il s'agit d'un homme et que l'âge est une valeur positive ;</li>
<li>valeur manquante enfin pour les autres cas.</li>
</ul>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#008000;">/*create table class as*/<br />
</span>   <span style="color:#0000ff;">select</span> *, <span style="color:#0000ff;">case<br />
</span>               <span style="color:#0000ff;">when</span> age &#62; <span style="color:#008080;"><strong>13</strong></span> <span style="color:#0000ff;">and</span> sex=<span style="color:#800080;">'F'</span> <span style="color:#0000ff;">then</span> <span style="color:#008080;">1</span><br />
               <span style="color:#0000ff;">when</span> age &#62;= <span style="color:#008080;"><strong>0</strong></span> <span style="color:#0000ff;">and</span> sex=<span style="color:#800080;">'F'</span> <span style="color:#0000ff;">then</span> <strong><span style="color:#008080;">2</span></strong><br />
               <span style="color:#0000ff;">when</span> age &#60; <span style="color:#008080;"><strong>0</strong></span> or sex not <span style="color:#0000ff;">in</span> (<span style="color:#800080;">'F'</span>,<span style="color:#800080;">'M'</span>) <span style="color:#0000ff;">then</span> .<br />
              <span style="color:#0000ff;"> else</span> <span style="color:#008080;"><strong>3<br />
</strong></span>          <span style="color:#0000ff;"> end as</span> pop<br />
   <span style="color:#0000ff;">from</span> sashelp.class;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p><strong>2.2 Utiliser les fonctions</strong></p>
<p>Dans l'exemple ci-dessous, le critère est appliqué par groupe de valeurs définies dans la variable SEX. En regardant les données, deux groupes de valeurs apparaissent : 'F' pour les femmes et 'M' pour les hommes. La variable MAX_AGE1 est égale à '13' si, pour un groupe donné, la valeur maximale observée parmi les valeurs non manquantes de la variable AGE est 13. Sinon, MAX_AGE1 prend la valeur 'N/A'.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">select</span> sex, <span style="color:#0000ff;">case</span><br />
                 <span style="color:#0000ff;">when</span> max(age) = 13 <span style="color:#0000ff;">then</span> <span style="color:#800080;">'13'</span><br />
                 <span style="color:#0000ff;">else</span> <span style="color:#800080;">'N/A'<br />
</span>               <span style="color:#0000ff;">end as</span> max_age1<br />
   <span style="color:#0000ff;">from</span> sashelp.class<br />
   <span style="color:#0000ff;">group</span> <span style="color:#0000ff;">by</span> sex;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p>A présent, vu qu'il n'y a qu'un critère définissant la condition et qu'une seule valeur n'est attendue, ce critère peut être donné en début.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">select</span> sex, <span style="color:#0000ff;">case </span>max(age)<br />
                 <span style="color:#0000ff;">when</span> (13) <span style="color:#0000ff;">then</span> <span style="color:#800080;">'13'</span><br />
                 <span style="color:#0000ff;">else</span> <span style="color:#800080;">'N/A'</span><br />
               <span style="color:#0000ff;">end as </span>max_age2<br />
   <span style="color:#0000ff;">from </span>sashelp.class<br />
   <span style="color:#0000ff;">group by </span>sex;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p>Mais, il est bon de se demander si un format ne serait pas plus adapté dans ce cas.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc format</span></strong>;<br />
  <span style="color:#0000ff;">value</span> max_age<br />
   <span style="color:#008080;"><strong>13    </strong></span>= <span style="color:#800080;">'13'<br />
</span>   other = <span style="color:#800080;">'N/A'</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
   <span style="color:#0000ff;">select</span> sex, put(max(age),<span style="color:#008080;">max_age.</span>) <span style="color:#0000ff;">as</span> max_age2<br />
   <span style="color:#0000ff;">from</span> sashelp.class<br />
   <span style="color:#0000ff;">group by</span> sex;<br />
<strong><span style="color:#000080;">quit</span></strong>; </span></p>
<p><strong>2.3 Créer une macro variable</strong></p>
<p>Voici pour terminer un petit exemple où une macro variable POP est crée. Sa valeur dépend de l'âge maximum observé dans le data set.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>; <span style="color:#008000;">*noprint;</span><br />
   <span style="color:#0000ff;">select case<br />
            when </span>max(age) &#62; <strong><span style="color:#008080;">13</span></strong> <span style="color:#0000ff;">then</span> <span style="color:#800080;">'&#62;13'</span><br />
            <span style="color:#0000ff;">when</span> max(age) &#62;= <strong><span style="color:#008080;">0</span></strong> <span style="color:#0000ff;">then</span> <span style="color:#800080;">'[0-13]'<br />
</span>            <span style="color:#0000ff;">else</span> 'N/A'<br />
          <span style="color:#0000ff;">end</span> <span style="color:#0000ff;">into</span> :pop<br />
   <span style="color:#0000ff;">from</span> sashelp.class;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Penser conditionnel (1/3) : La base du IF]]></title>
<link>http://thesasreference.wordpress.com/?p=151</link>
<pubDate>Thu, 19 Jun 2008 06:00:15 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=151</guid>
<description><![CDATA[
Selon que des variables aient certaines valeurs ou non, le programmeur peut décider de créer u]]></description>
<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-167" src="http://thesasreference.wordpress.com/files/2008/06/bouda_fr.jpg" alt="" width="435" height="224" /></p>
<p>Selon que des variables aient certaines valeurs ou non, le programmeur peut décider de créer une nouvelle variable, extraire une ligne d'observation, etc.</p>
<p>SAS propose plusieurs syntaxes pour exprimer ces conditions.</p>
<ul>
<li>Dans le data step et la procédure SQL, pour extraire un sous ensemble de records sans autre action le WHERE est probablement le plus adapté. De plus, dans d'autres cas que le data step et la PROC SQL l'option WHERE est aussi utilisable (PROC SORT, PROC FREQ, ODS OUTPUT...).</li>
<li>Sinon, dans un data step, on rencontre le IF et le SELECT et dans une procédure SQL, CASE WHEN est disponible. </li>
</ul>
<p>Ce sujet sera divisé en 3 articles à commencer par la syntaxe du IF. Dans huit jours, le prochain rendez-vous sera consacré au SELECT. Enfin le dernier article de la série s'intéressera au CASE WHEN.</p>
<p><strong><span style="color:#ff6600;">1. Le minimum ou presque</span></strong></p>
<p>"S'il pleut, alors je prend mon parapluie, sinon, je le laisse au bureau." Dans cette phrase, on repère trois mots : si, alors, sinon. Traduisez par IF, THEN, ELSE. C'est trois mots, version anglaise, forme la syntaxe de base.</p>
<p>Dans l'exemple suivant, on considère les variables AGE et SEX pour créer la variable PP_NY (per protocol population, no/yes) : "Si ma variable âge est supérieure à 13 et qu'il s'agit d'hommes alors ma variable pp_ny=1, sinon pp_ny=0."</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> class;<br />
   <span style="color:#0000ff;">set</span> sashelp.class;<br />
   <span style="color:#0000ff;">if</span> age &#62; <span style="color:#008080;"><strong>13</strong></span> and sex=<span style="color:#800080;">'M'</span> <span style="color:#0000ff;">then</span> pp_ny=<strong><span style="color:#008080;">1</span></strong>;<br />
   <span style="color:#0000ff;">else</span> pp_ny=<span style="color:#008080;"><strong>0</strong></span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>On remarquera l'usage de l'instruction finale ELSE pour incluse tous les cas non pris en compte précédemment.</p>
<p><span style="color:#ff6600;"><strong>2. Multiplier les combinaisons</strong></span></p>
<p>Dans ce second exemple, une instruction ELSE IF a été ajoutée. Ainsi tous les hommes de 13 ans ou moins pour lesquels on connaît l'âge sont sélectionnée dans cette seconde instruction. Enfin, les valeurs restantes correspondent aux lignes d'observations où l'âge est manquant ou concernant les femmes.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> class;<br />
   <span style="color:#0000ff;">set</span> sashelp.class;<br />
   <span style="color:#0000ff;">if</span> age &#62; <span style="color:#008080;"><strong>13</strong></span> and sex=<span style="color:#800080;">'M'</span> <span style="color:#0000ff;">then</span> pp_ny=<strong><span style="color:#008080;">1</span></strong>;<br />
   <span style="color:#0000ff;">else if </span>age &#62; <strong><span style="color:#008080;">.z</span></strong> and sex=<span style="color:#800080;">'M'</span> <span style="color:#0000ff;">then</span> pp_ny=<span style="color:#008080;"><strong>0</strong></span>;<br />
   <span style="color:#0000ff;">else</span> pp_ny=<span style="color:#008080;">.</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong></strong></p>
<p><strong>ELSE IF</strong> : il est préférable d'utiliser le ELSE IF, plutôt que le IF pour des raisons de performance et pour éviter des erreurs d'étourderie.</p>
<ul>
<li>Par performance j'entends : seules les observations qui ne sont pas valides dans la première condition sont lues pour évaluer la condition suivante. C'est un temps très précieux quand on traite une grosse base de données. </li>
<li>Par erreur j'entends : en aucun cas, des observations peuvent-être sélectionnées par deux instructions. Ainsi si PP_NY=1, il n'y a aucune chance qu'il devienne PP_NY=0 après exécution de la seconde instruction.</li>
</ul>
<p><strong>Important </strong>: dans l'exemple précédent, j'ai volontairement choisi de lister plus d'une variable pour définir ma condition. En effet, si vous avez une seule variable en entrée et une seule variable en sortie, un informat suffit. Plusieurs avantages se cachent derrière :</p>
<ul>
<li>le programme est allégé</li>
<li>l'accès aux valeurs est plus évident puisque les formats font partie des informations données en début de programme.</li>
</ul>
<p>Voici ce que cela donnerait si on ne considérerait que la variable AGE pour définir la variable PP_NY.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc format</span></strong>;<br />
<span style="color:#0000ff;">   invalue</span> age_pp<br />
<span style="color:#008080;"><strong>   ._</strong></span>-<span style="color:#008080;"><strong>.z</strong></span>    = <span style="color:#008080;"><strong>.</strong></span><br />
   low-<span style="color:#008080;"><strong>13   </strong></span>= <strong><span style="color:#008080;">0<br />
</span><span style="color:#008080;">   13</span></strong>&#60;-high = <span style="color:#008080;"><strong>1</strong></span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> class;<br />
<span style="color:#0000ff;"><strong>   set</strong></span> sashelp.class;<br />
   pp_ny=input(age,<span style="color:#008080;">age_pp.</span>);<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="color:#ff6600;"><strong>3. Parenthèse sur les valeurs manquantes</strong> </span></p>
<p>On a fait très attention de ne pas inclure les âges manquants pour définir PP_NY=1/0. La valeur .z est une valeur manquante spéciale "special missing". SAS en compte 27.</p>
<p><strong>L'intérêt des valeurs manquantes spéciales</strong> : le but des special missings est d'offrir d'un éventail de valeurs pour distinguer les valeurs manquantes. Prenez le cas d'une variable indiquant le contraceptif médicamenteux pris par le patient. S'il s'agit d'une femme et que l'information n'est pas fournie, on mettra manquant (un point). Par contre, s'il s'agit d'un homme, on marquera .A pour "non applicable". Un format permettra ensuite de représenter . par MISSING et .A par N/A.</p>
<p><strong>L'ordre des valeurs manquantes</strong> : l'ordre des missings et special missings est important à connaître. Cela vous expliquera pourquoi j'ai utiliser .z et non . dans l'exemple précédent. Vous pouvez vous reporter à la Online Doc : <a title="Missing Values" href="http://support.sas.com/onlinedoc/913/getDoc/de/lrcon.hlp/a001292604.htm">Missing Values</a>. En résumé cela donne :</p>
<ul>
<li>._ pour le plus petit,</li>
<li>. juste après,</li>
<li>.A</li>
<li>...</li>
<li>.Z pour le plus grand des special missings</li>
<li>valeurs négatives</li>
<li>valeurs positives</li>
</ul>
<p><strong>Alternative avec la fonction MISSING</strong> : sachez qu'une autre solution pour exclure tous les valeurs manquantes (missing et special missing), c'est d'utiliser la fonction MISSING quia pour autre avantage de s'appliquer autant aux valeurs textes qu'aux valeurs numériques. C'est très pratique quand on ne connaît pas à l'avance le type de la variable. Dans la PROC SQL, WHERE... il y a aussi "WHERE x IS MISSING".</p>
<p><strong><span style="color:#ff6600;">4. Plusieurs actions quand une condition est remplie (DO-END)</span></strong></p>
<p>Si une condition est remplie, il peut s'avérer nécessaire de faire plusieurs choses. Par exemple, on peut à la fois créer une nouvelle variable et sortir la ligne d'observation.</p>
<p>Dans l'exemple ci-dessous, la variable SEX ne prend que les valeurs 'M' et 'F'. Dans ce cas précis, au final, il y a plus de records à la fin. Tout d'abord, tous les records sont extraits et POP est défini comme étant égal à 1. Ensuite, pour les records masculins, les records sont sortis une deuxième fois et notre variable POP est alors égale à 2.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>data</strong></span> class;<br />
   <span style="color:#0000ff;">set</span> sashelp.class;<br />
   pop=<strong><span style="color:#008080;">1</span></strong>;<br />
   <span style="color:#0000ff;">output</span>;<br />
   <span style="color:#0000ff;">if </span>sex=<span style="color:#800080;">'M'</span> <span style="color:#0000ff;">then</span><br />
     <span style="color:#0000ff;">do</span>;<br />
        pop=<span style="color:#008080;"><strong>2</strong></span>;<br />
        <span style="color:#0000ff;">output</span>;<br />
     <span style="color:#0000ff;">end</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Mes valeurs sont t'elles proches de la moyenne ? (écart-type)]]></title>
<link>http://thesasreference.wordpress.com/?p=150</link>
<pubDate>Tue, 17 Jun 2008 06:00:12 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=150</guid>
<description><![CDATA[Pour résumer une série de mesures, il est courant de proposer la moyenne. Mais avoir une moyenne ]]></description>
<content:encoded><![CDATA[<p>Pour 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 <strong><em>standard deviation</em></strong> 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.</p>
<p><strong><span style="color:#ff6600;">1. Des variables continues</span></strong></p>
<p>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.</p>
<p>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.</p>
<p><strong><span style="color:#ff6600;">2. Définition l'écart-type d'une population</span></strong></p>
<p>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.</p>
<p><strong>1. Mettre au carré les différences</strong> : 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é).</p>
<p>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.</p>
<p><strong>2. Extraire la moyenne</strong> : 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 <strong>variance</strong>.</p>
<p><strong>3. Exprimer la dispersion dans la même unité que la moyenne :</strong> 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.</p>
<p><strong><span style="color:#ff6600;">3. Estimer l'écart-type d'une population à partir d'un échantillon</span></strong></p>
<p><strong>Contexte</strong> : 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.</p>
<p><strong>Le problème</strong> : 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.</p>
<p><strong>La solution</strong> : 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).</p>
<p><strong>Vocabulaire</strong> : Et pour enrichir votre vocabulaire et surtout comprendre ces spécialistes sachez que si l'écart-type sera appelé un estimateur <strong>biaisé</strong> si le 1 n'est pas enlevé.</p>
<p>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.</p>
<p><strong><span style="color:#ff6600;">4. Comprendre la différence entre l'écart-type et l'erreur-type</span></strong></p>
<p>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). </p>
<p>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. </p>
<p>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é.</p>
<p><strong><span style="color:#ff6600;">5. En langage mathématique, l'écart-type donne quoi ?</span></strong></p>
<p>Pour désigner nos valeurs, le mathématicien utilise la lettre X.</p>
<ul>
<li>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.</li>
<li>La moyenne de ces Xi est symbolisée par un X avec une barre au dessus.</li>
</ul>
<p>Pour calculer l'écart-type, on a parlé de trois étapes :</p>
<ol>
<li><strong>sum(Xi-Xbar)2</strong> 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.</li>
<li><strong>sum(Xi-Xbar)2 / (n-1)</strong> Après, il s'agit de calculer la moyenne de ces valeurs</li>
<li><strong>racine(sum(Xi-Xbar)2 / (n-1))</strong> Enfin, la statistique est convertie en une unité comparable à celle de la moyenne via la racine carré.</li>
</ol>
<p><strong><span style="color:#ff6600;">6. Et en langage SAS, comment trouver la valeur d'un écart-type ?</span></strong></p>
<p>Dans tous les cas suivant, le dénominateur est n-1.</p>
<p><strong>6.1 Fonction STD</strong> : La fonction STD (<em>standard deviation</em>) retourne la valeur de l'écart-type.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
<span style="color:#0000ff;">   select</span> std(age)<span style="color:#0000ff;"> as </span>std_age<br />
<span style="color:#0000ff;">   from</span> sashelp.class;<br />
<strong><span style="color:#000080;">quit</span></strong>;</span></p>
<p><strong>6.2 Calcul manuel</strong> : 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.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sql</span></strong>;<br />
<span style="color:#0000ff;">   create table</span> step1 <span style="color:#0000ff;">as<br />
</span><span style="color:#0000ff;">      select </span>(age-mean(age))**2 <span style="color:#0000ff;">as</span> step1<br />
<span style="color:#0000ff;">      from</span> sashelp.class;<br />
<span style="color:#0000ff;">   select</span> sqrt(sum(step1)/(count(*)-1)) as step2_3<br />
<span style="color:#0000ff;">      from</span> step1;<br />
<strong><span style="color:#0000ff;">quit</span></strong>;</span></p>
<p><strong>6.3 Les procédures PROC MEANS et PROC SUMMARY</strong> : dans les exemples ci-dessous, j'ai volontairement choisi l'instruction ODS OUTPUT pour extraire les statistiques dans un data set.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc means</span></strong> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
<span style="color:#0000ff;">var</span> age;<br />
<span style="color:#0000ff;">ods output</span> Summary=proc_means;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc summary</span></strong> <span style="color:#0000ff;">data</span>=sashelp.class <span style="color:#0000ff;">print</span>;<br />
<span style="color:#0000ff;">   var</span> age;<br />
<span style="color:#0000ff;">   ods output</span> Summary=proc_summary;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>6.4 La procédure PROC UNIVARIATE</strong> : deux sorties fournies par la procédure UNIVARIATE sont indifféremment disponible.</p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc univariate</strong></span> <span style="color:#0000ff;">data</span>=sashelp.class;<br />
<span style="color:#0000ff;">   var</span> age;<br />
<span style="color:#0000ff;">   ods output</span> Moments=proc_univ_opt1;<br />
<span style="color:#0000ff;">   ods output</span> BasicMeasures=proc_univ_opt2;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Jongler avec les records grâce aux compteurs]]></title>
<link>http://thesasreference.wordpress.com/?p=145</link>
<pubDate>Thu, 12 Jun 2008 06:00:25 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=145</guid>
<description><![CDATA[Sous SAS, une variable compteur permet de numéroter les lignes d&#8217;observations. Le plus souven]]></description>
<content:encoded><![CDATA[<p>Sous SAS, une variable compteur permet de numéroter les lignes d'observations. Le plus souvent, cette variable sert ensuite à sélectionner certaines lignes d'un jeu de données et d'agir en fonction. Par exemple, pour chaque patient, un fois le compteur créé, il est simple de sélectionner les 5 premiers records.</p>
<p>Pour développer une variable compteur, il faut maîtriser la notion de FIRST. Vous pouvez vous reporter à l'article "<a href="http://thesasreference.wordpress.com/2008/05/06/first_last/">Repérer les 1ers/derniers records (FIRST/LAST</a>)".</p>
<p>En outre, il faut comprendre la notion de RETAIN. Celle-ci sera abordée dans cet article.</p>
<p>Quatre exemples serviront à illustrer le sujet. Ils sont basés sur un data set nommé LAB ayant 9 lignes observations. Il est donné en fin d'article dans le paragraphe "Annexe". On y trouve trois patients (PAT_ID), deux types de tests médicaux (TEST) et une date pour chaque test (variable TEST_DT). La variable compteur s'appelle à chaque fois CNT.</p>
<p> <strong><span style="color:#ff6600;">1. La notion de RETAIN</span></strong></p>
<p>Un RETAIN permet d'assigner une valeur à toutes les observations d'une variable. On préfèrera donc un RETAIN à "variable=valeur;" pour assigner une valeur unique pour toutes les records d'une variable données. </p>
<p>Si entre temps, la valeur d'une observation est modifiée, tous les valeurs suivantes prennent cette nouvelle valeur. Cette seconde fonctionnalité sert pour créer une variable compteur.</p>
<p>Un RETAIN se définit le plus souvent dans une instruction RETAIN. Dans le cas des compteurs, on peut créer un RETAIN implicite prenant une valeur d'origine de zéro.</p>
<p><strong><span style="color:#ff6600;">2. Pour chaque nouvelle observation incrémenter le compteur</span></strong> : dans ce premier exemple, à chaque nouvelle observation identifiée de manière unique par PAT_ID, TEST_DT et TEST, le compteur est incrémenté par 1. Le compteur va alors de 1 à 9 (le total d'observations). Les données sont préalablement triées par ces trois variables.</p>
<p><span style="font-family:Courier New;">  test_dt    pat_id    test    cnt</span></p>
<p><span style="font-family:Courier New;">28MAR2006      101     DBP      1<br />
28MAR2006      101     SBP      2<br />
29APR2006      101     DBP      3<br />
27MAY2006      101     SBP      4<br />
23JUN2006      101     SBP      5<br />
13JAN2006      301     DBP      6<br />
14FEB2006      301     SBP      7<br />
15MAR2006      301     DBP      8<br />
05MAR2006      401     DBP      9</span></p>
<p>Il faut donc dans un premier temps trier les données et rappeler cet ordre dans l'instruction BY du data step.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sort</span></strong> <span style="color:#0000ff;">data</span>=lab;<br />
   <span style="color:#0000ff;">by</span> pat_id test_dt test;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>Puis la variable CNT prend une valeur de 0 pour chaque record.</p>
<p>Enfin les records sont lus les uns après les autres. A chaque nouvelle TEST pour un PAT_ID et TEST_DT donné, le compteur est incrémenté de 1.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> lab;<br />
   <span style="color:#0000ff;">retain</span> cnt <strong><span style="color:#008080;">0</span></strong>;<br />
   <span style="color:#0000ff;">set</span> lab;<br />
   <span style="color:#0000ff;">by</span> pat_id test_dt test;<br />
   <span style="color:#0000ff;">if</span> first.test <span style="color:#0000ff;">then</span> cnt=cnt+<strong><span style="color:#008080;">1</span></strong>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>Un RETAIN implicite</strong> : l'instruction RETAIN peut-être omise si un RETAIN implicite est utilisé. C'est le cas ici quand "cnt=cnt+1" est remplacé par "cnt+1".</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> lab;<br />
   <span style="color:#0000ff;">set</span> lab;<br />
   <span style="color:#0000ff;">by</span> pat_id test_dt test;<br />
   <span style="color:#0000ff;">if</span> first.test <span style="color:#0000ff;">then</span> cnt+<span style="color:#008080;"><strong>1</strong></span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="color:#ff6600;"><strong>3. Pour chaque nouvelle date, incrémenter le compteur</strong> </span>: dans le second exemple, pour chaque nouvelle date indépendamment du patient ou de type de test, le compteur est incrémenté par 1. Le compteur va de 1 à 8 (les 8 différentes dates). Les données sont triées par date au préalable.</p>
<p><span style="font-family:Courier New;">  test_dt    pat_id    test    cnt</span></p>
<p><span style="font-family:Courier New;">13JAN2006      301     DBP      1<br />
14FEB2006      301     SBP      2<br />
05MAR2006      401     DBP      3<br />
15MAR2006      301     DBP      4<br />
<span style="color:#ff6600;">28MAR2006</span>      101     SBP      <span style="color:#ff6600;">5<br />
</span><span style="color:#ff6600;">28MAR2006</span>      101     DBP      <span style="color:#ff6600;">5<br />
</span>29APR2006      101     DBP      6<br />
27MAY2006      101     SBP      7<br />
23JUN2006      101     SBP      8</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sort</span></strong> <span style="color:#0000ff;">data</span>=lab;<br />
   <span style="color:#0000ff;">by</span> test_dt;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> lab;<br />
   <span style="color:#0000ff;">set</span> lab;<br />
   <span style="color:#0000ff;">by</span> test_dt;<br />
   <span style="color:#0000ff;">if</span> first.test_dt <span style="color:#0000ff;">then</span> cnt+<span style="color:#008080;"><strong>1</strong></span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="color:#ff6600;"><strong>4. Pour chaque nouveau patient, incrémenter le compteur</strong> </span>: dans ce troisième exemple, chaque patient reçoit un numéro unique allant de 1 à 3 ; trois étant le nombre total de patients. Les données sont donc triées par PAT_ID.</p>
<p><span style="font-family:Courier New;">   test_dt    pat_id    test    cnt</span></p>
<p><span style="font-family:Courier New;">28MAR2006      <span style="color:#ff6600;">101</span>     SBP      <span style="color:#ff6600;">1</span><br />
28MAR2006      101     DBP      1<br />
27MAY2006      101     SBP      1<br />
23JUN2006      101     SBP      1<br />
29APR2006      101     DBP      1<br />
14FEB2006      <span style="color:#ff6600;">301</span>     SBP      <span style="color:#ff6600;">2<br />
</span>13JAN2006      301     DBP      2<br />
15MAR2006      301     DBP      2<br />
05MAR2006      <span style="color:#ff6600;">401</span>     DBP      <span style="color:#ff6600;">3</span></span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">proc sort</span></strong> <span style="color:#0000ff;">data</span>=lab;<br />
   <span style="color:#0000ff;">by </span>pat_id;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>data</strong></span> lab;<br />
   <span style="color:#0000ff;">set</span> lab;<br />
   <span style="color:#0000ff;">by</span> pat_id;<br />
   <span style="color:#0000ff;">if</span> first.pat_id <span style="color:#0000ff;">then</span> cnt+<span style="color:#008080;"><strong>1</strong></span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong><span style="color:#ff6600;">5. Pour chaque nouveau date d'un patient donné, incrémenter le compteur</span></strong> : dans ce dernier exemple, à chaque nouvelle date, le compteur est incrémenté par un. Le premier patient ayant 4 dates différentes et 5 observations, le compteur va de 1 à 4 pour lui. Une des valeurs est doublée pour la date identique. Le second patient ayant trois dates uniques, le compteur va de 1 à 3 pour lui. Le compteur est donc réinitialisé à 1 pour chaque nouveau patient.</p>
<p><span style="font-family:Courier New;">  test_dt    pat_id    test    cnt</span></p>
<p><span style="font-family:Courier New;"><span style="color:#ff6600;">28MAR2006</span>      <span style="color:#ff6600;">101     SBP      </span><span style="color:#ff6600;">1<br />
</span><span style="color:#ff6600;">28MAR2006</span>      101     DBP      <span style="color:#ff6600;">1</span><br />
29APR2006      101     DBP      2<br />
27MAY2006      101     SBP      3<br />
23JUN2006      101     SBP      4<br />
<span style="color:#ff6600;">13JAN2006      301     DBP      1</span><br />
14FEB2006      301     SBP      2<br />
15MAR2006      301     DBP      3<br />
<span style="color:#ff6600;">05MAR2006      401     DBP      1</span></span></p>
<p><span style="font-family:Courier New;"><span style="color:#000080;"><strong>proc sort</strong> </span><span style="color:#0000ff;">data</span>=lab;<br />
   <span style="color:#0000ff;">by</span> pat_id test_dt;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> one;<br />
   <span style="color:#0000ff;">set</span> orig;<br />
   <span style="color:#0000ff;">by</span> pat_id test_dt;<br />
   <span style="color:#0000ff;">if</span> first.pat_id<span style="color:#0000ff;"> then </span>cnt=1;<br />
   <span style="color:#0000ff;">else if </span>first.test_dt <span style="color:#0000ff;">then</span> cnt+1;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p><strong>Annexe</strong> :</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> orig;<br />
   <span style="color:#0000ff;">format </span>test_dt <span style="color:#008080;">date9.;</span><br />
   <span style="color:#0000ff;">input</span> pat_id test_dt <span style="color:#008080;">date9.</span> test_type $;<br />
   <span style="color:#0000ff;">datalines</span>;<br />
101 28MAR2006 SBP<br />
101 28MAR2006 DBP<br />
101 27MAY2006 SBP<br />
101 23JUN2006 SBP<br />
301 14FEB2006 SBP<br />
101 29APR2006 DBP<br />
301 13JAN2006 DBP<br />
301 15MAR2006 DBP<br />
401 05MAR2006 DBP<br />
;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Jerarquia de Directorios - Linux]]></title>
<link>http://julianrdz.wordpress.com/?p=153</link>
<pubDate>Wed, 11 Jun 2008 22:28:53 +0000</pubDate>
<dc:creator>Julián Rodríguez</dc:creator>
<guid>http://julianrdz.wordpress.com/?p=153</guid>
<description><![CDATA[
 / (raíz): Es el nivel más alto dentro de la jerarquía de directorios. De aquí cuelgan el resto]]></description>
<content:encoded><![CDATA[<ul>
<li><strong> / (raíz):</strong> Es el nivel más alto dentro de la jerarquía de directorios. De aquí cuelgan el resto de carpetas, particiones y otros dispositivos. Es por esto que donde se instala el sistema, se selecciona la partición deseada y se le indica que el punto de montaje es justamente /.</li>
</ul>
<ul>
<li><strong>/bin (binarios): </strong>Los binarios son los ejecutables de Linux. Aquí tendremos los ejecutables de los programas propios del sistema operativo, entre ellos comandos como cp, mv, cat, chown, etc. No es el único directorio que contiene ejecutables como veremos más adelante.</li>
</ul>
<ul>
<li><strong>/boot (arranque):</strong> Aquí nos encontramos los archivos necesarios para el inicio del sistema, desde los archivos de configuración de Grub Lilo, hasta el propio kernel del sistema.</li>
</ul>
<ul>
<li><strong>/dev (dispositivos):</strong> Linux se basa en la simpleza y en el tratamiento homogéneo de la información. Linux trata los dispositivos como si fueran un fichero más para facilitar el flujo de la información. En esta carpeta tenéis los dispositivos del sistema, por ejemplo los usb, sda (o hda) con sus respectivos números que indican las particiones, etc.</li>
</ul>
<ul>
<li><strong>/etc (etcétera): </strong>Aquí se guardan los ficheros de configuración de los programas instalados, así como ciertos scripts que se ejecutan en el inicio del sistema. Los valores de estos ficheros de configuración pueden ser complementados o sustituidos por los ficheros de configuración de usuario que cada uno tiene en su respectivo “home” (carpeta personal).</li>
</ul>
<ul>
<li><strong>/home (hogar):</strong> Este hogar no es más que un directorio que a su vez contiene otros, uno por cada usuario dado de alta en el sistema. Dentro de dichos directorios es donde el usuario tiene su carpeta personal, donde están los ficheros de configuración de usuario, así como los archivos personales del mismo que puede crear, modificar y eliminar bajo su propio criterio.</li>
</ul>
<ul>
<li><strong>/lib (bibliotecas):</strong> Contiene las bibliotecas (tambien mal conocidas como librerías) del sistema, así como módulos y controladores (drivers).</li>
</ul>
<ul>
<li><strong>/lost+found (perdido y encontrado): </strong>Es una carpeta que nos podemos encontrar en todas las particiones. Cuando por cualquier circunstancia se cierra mal el sistema (un apagón por ejemplo), cuando éste se reinicie comprobaréis que se llamará al programa fsck para restaurar la integridad del sistema de ficheros. En esta carpeta encontraremos la información que se mal-guardó debido a la incidencia.</li>
</ul>
<ul>
<li><strong>/media (media/medios): </strong>Es donde se montan las unidades extraíbles como los dispositivos USB, disqueteras, unidades de CD/DVD y en algunas distros, como Ubuntu, las particiones adicionales.</li>
</ul>
<ul>
<li><strong>/mnt (montajes):</strong> Es un directorio que se suele usar para montajes temporales de unidades.</li>
</ul>
<ul>
<li><strong>/opt (opcionales):</strong> Destinado para guardar paquetes adicionales de aplicaciones.</li>
</ul>
<ul>
<li><strong>/proc:</strong> Información para la virtualización del sistema de ficheros de Linux.</li>
</ul>
<ul>
<li><strong>/root:</strong> Es el /home del administrador. Es el único /home que no está incluido -por defecto- en el directorio anteriormente mencionado.</li>
</ul>
<ul>
<li><strong>/sbin (binarios de sistema): </strong>Son los ejecutables de administración, tales como mount, umount, shutdown…</li>
</ul>
<ul>
<li><strong>/srv (servicios):</strong> Información del sistema sobre ciertos servicios que ofrece (FTP, HTTP…).</li>
</ul>
<ul>
<li><strong>/sys (sistema):</strong> Información sobre los dispositivos tal y como los ve el kernel Linux.</li>
</ul>
<ul>
<li><strong>/tmp (temporales):</strong> Es un directorio donde se almacenan ficheros temporales. Cada vez que se inicia el sistema este directorio se limpia.</li>
</ul>
<ul>
<li><strong>/usr: </strong>Es el directorio padre de otros subdirectorios de importancia:
<ul>
<li><strong>/usr/bin:</strong> Conjunto de ejecutables de la mayoría de aplicaciones de escritorio entre otras (por ejemplo firefox).</li>
<li><strong>/usr/include:</strong> Los ficheros cabeceras para C y C++.</li>
<li><strong>/usr/lib: </strong>Las bibliotecas para C y C++.</li>
<li><strong>/usr/local: </strong>Es otro nivel dentro que ofrece una jerarquía parecida al propio diretorio /usr.</li>
<li><strong>/usr/sbin: </strong>Otra serie de comandos administrativos para el sistema.</li>
<li><strong>/usr/share: </strong>Archivos compartidos como ficheros de configuración, imágenes, iconos, etc.</li>
<li><strong>/usr/src: </strong>Tiene en su interior el código fuente para el kernel LInux.</li>
</ul>
</li>
</ul>
<ul>
<li><strong>var: </strong>Ficheros de sistema como el buffer de impresión, logs…
<ul>
<li><strong>/var/cache:</strong> Se almacenan datos cacheados para las aplicaciones.</li>
<li><strong>/var/lib:</strong> Información sobre el estado actual de las aplicaciones, modificable por las propias aplicaciones.</li>
<li><strong>/var/lock:</strong> Ficheros que se encargan de que un recurso sólo sea usado por una aplicación determinada que ha pedido su exclusividad, hasta que ésta lo libere.</li>
<li><strong>/var/log: </strong>Es uno de los subdirectorios más importantes ya que aquí se guardan todo tipo de logs del sistema.</li>
<li><strong>/var/mail:</strong> Los correos de los usuarios.</li>
<li><strong>/var/opt: </strong>Datos usados por los paquetes almacenados en /opt.</li>
<li><strong>/var/run:</strong> Información sobre el sistema desde que se inició.</li>
<li><strong>/var/spool:</strong> Datos esperando a que sean tratados por algún tipo de proceso.</li>
<li><strong>/var/tmp:</strong> Otro fichero temporal.</li>
</ul>
</li>
</ul>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Insérer quelques nouvelles observations]]></title>
<link>http://thesasreference.wordpress.com/?p=141</link>
<pubDate>Mon, 09 Jun 2008 06:00:05 +0000</pubDate>
<dc:creator>The SAS Reference</dc:creator>
<guid>http://thesasreference.wordpress.com/?p=141</guid>
<description><![CDATA[Dans l&#8217;article &#8216;Ajouter des lignes en combinant des data sets&#8217;, nous avons vu comm]]></description>
<content:encoded><![CDATA[<p>Dans l'article <a href="http://www.sasreference.com/2008/05/22/ajouter_lignes_datasets/">'Ajouter des lignes en combinant des data sets'</a>, nous avons vu comment ajouter des observations en joignant plusieurs data sets. Ici, il s'agit de voir comment ajouter manuellement un nombre limité d'observations en fin de data set. Deux méthodes sont proposées : un data step avec l'option END= et l'instruction OUTPUT d'une part et l'instruction INSERT INTO de PROC SQL d'autre part.</p>
<p><strong><span style="color:#ff6600;">1. Passer par un data step pour ajouter une ou plusieurs observations</span></strong></p>
<p>L'instruction SET dispose de l'option END=. Celle-ci permet de définir une nouvelle variable. On peut s'imaginer cette variable comme une variable binaire prenant une valeur zéro pour toutes les observations sauf la dernière. Il est courant de nommer cette variable EOF, acronyme pour END OF FILE (fin de fichier).</p>
<p>Dans un premier temps, toutes les observations sont lues et envoyées dans le data set de sortie avec OUTPUT.</p>
<p>Dans un second temps, on précise à SAS que si notre variable binaire a une valeur de 1, l'observation va être de nouveau envoyée dans le data set final après avoir changé les valeurs de son choix.</p>
<p>Lorsque la valeur prise par la variable binaire n'est pas précisée (if eof then...), SAS assume 'if eof=1 then...' ou en d'autres termes 'si la condition est vraie alors...'. Pour information, l'inverse est 'if not eof then...' ou 'if eof=0 then...'.</p>
<p><span style="font-family:Courier New;"><strong><span style="color:#000080;">data</span></strong> class;<br />
   <span style="color:#0000ff;">set</span> sashelp.class end=eof;<br />
   <span style="color:#0000ff;">output</span>;<br />
   <span style="color:#0000ff;">if </span>eof <span style="color:#0000ff;">then</span><br />
      <span style="color:#0000ff;">do</span>;<br />
         name=<span style="color:#800080;">'SASREF'</span>;<br />
         sex=<span style="color:#800080;">'F'</span>;<br />
         age=<span style="color:#008080;"><strong>18</strong></span>;<br />
         height=<strong><span style="color:#008080;">.</span></strong>;<br />
         weight=<strong><span style="color:#008080;">100</span></strong>;<br />
         <span style="color:#0000ff;">output</span>;<br />
         name=<span style="color:#800080;">'SASREF'</span>;<br />
         sex=<span style="color:#800080;">'M'</span>;<br />
         age=<span style="color:#008080;"><strong>.</strong></span>;<br />
         height=<strong><span style="color:#008080;">.</span></strong>;<br />
         weight=<strong><span style="color:#008080;">.</span></strong>;<br />
         <span style="color:#0000ff;">output</span>;<br />
<span style="color:#0000ff;">      end</span>;<br />
<strong><span style="color:#000080;">run</span></strong>;</span></p>
<p>Cette méthode reste très contraignante. Car il faut redéfinir tous les champs au risque sinon d'avoir une valeur de l'ancienne observation. La procédure SQL est véritablement conçue pour répondre à notre besoin.</p>
<p><span style="color:#ff6600;"><strong>2. L'instruction INSERT de la procédure PROC SQL</strong></span></p>
<p>Deux syntaxes sont disponibles avec l'instruction INSERT selon qu'on liste seulement les valeurs, mais pour toutes les variables ou qu'on liste à la fois les variables et leur valeurs mais seulement celles qui nous intéresse.</p>
<p>Ma préférence va à la seconde solution, car elle évite des erreurs dans l'ordre d'affichage des valeurs. De plus, lorsqu'on relit un programme, il est facile de faire le lien entre une valeur et la variable à laquelle elle réfère.</p>
<p><strong> 2.1 Lister toutes les va