logo

La procédure TABULATE, sa vie, son œuvre

Dotée d’une syntaxe joueuse, dont la ponctuation est un vrai casse-tête chinois, on ne peut pas dire que la procédure TABULATE génère spontanément la sympathie. Cela dit, dans tous les casses-têtes, on trouve une logique implacable – le but de ces pages est de décortiquer celle de TABULATE.

Petit itinéraire de vacances au pays des tableaux sous SAS.

 

Les préparatifs : syntaxe de base

 

PROC TABULATE DATA = tableLue ;
   CLASS variables1 ;
   VAR variables2 ;
   TABLE … ;
RUN ;

 

Comme souvent dans SAS, tout commence avec une option DATA= pour indiquer quelle est la table sur laquelle on souhaite travailler. Puis viennent deux instructions, VAR et CLASS, qui permettent de planter le décor, et d’indiquer les rôles des différentes variables :

• Toutes les variables de CLASS servent à définir des groupes d’observations sur lesquels les statistiques du tableau seront calculées. Ce seront les variables qui définiront les lignes et les colonnes du tableau. A ce stade, SAS ne distingue pas encore de notion de lignes et de colonnes : on peut donc mettre tous les noms de variables sans se soucier de leur ordre.

• Toutes les variables de VAR doivent être numériques ; ce sont sur ses variables que les statistiques du tableau seront calculées.
Il n’est pas obligatoire d’avoir défini les deux instructions : pour un tableau ne contenant que des tableaux et des pourcentages, par exemple, il n’y aura pas d’instruction VAR. En revanche, on ne peut pas faire fonctionner TABULATE sans avoir au moins une de ces instructions. Dans l’instruction TABLE, on définira plus précisément l’architecture du tableau. La logique de cette instruction est détaillée au paragraphe suivant.

 

Navigation au GPS : construire des tableaux croisés

 

C’est au niveau de l’instruction TABLE que se joue la mise en forme du tableau.

Elle est extrêmement sensible à la ponctuation :

• la virgule marque la limite entre les lignes et les colonnes ;

• l’espace indique une juxtaposition de deux éléments dans la même dimension (ligne ou colonne) ;

• l’étoile signifie que l’on imbrique deux éléments dans une même dimension.

La syntaxe de base est souvent :

TABLE (lignes ) ,
      (colonnes) *
      (cellules)
 ;

 

Entre les parenthèses de la dimension ligne, on trouve des noms de variables citées dans CLASS, ainsi que le mot-clé ALL qui indique un récapitulatif. Il en va de même entre les parenthèses de la dimension colonne.

Pour les cellules, on retrouve soit une statistique comme une fréquence ou un pourcentage, soit une variable de calcul (déjà citée dans VAR) suivie d’une étoile et de sa statistique.

 

La procédure TABULATE

 

Quelques exemples d’instructions TABLE vont vous aider à mieux comprendre l’intrication des différents composants.

Voici les données de départ (table SASHELP.PRDSALE)

La procédure TABULATE

 

On a ici la version « simple » du tableau : une variable en ligne, une en colonne, et des comptages dans les cellules.

PROC TABULATE DATA = sashelp.prdsale ;
   CLASS product country ;
   TABLE (country),
         (product)*
         (N) ;
RUN ;

La procédure TABULATE

 

Seconde version, avec une variable de calcul (ACTUAL) dont on calcule la moyenne.

CLASS product country ;
VAR actual ;
TABLE (country),
      (product)*
      (actual * MEAN) ;

La procédure TABULATE

 

Variante du tableau précédent avec en sus une ligne récapitulative (ALL). A noter que cette ligne supplémentaire n’est pas un total, mais bien un récapitulatif de la variable en ligne : ici, on aura des moyennes générales, et pas une somme des moyennes, en bas de chaque colonne. L’espace qui sépare le ALL de COUNTRY indique que le détail par pays précède la ligne récapitulative. On aurait écrit ALL COUNTRY pour avoir le récapitulatif en première ligne du tableau.

TABLE (country ALL),
      (product)*
      (actual * MEAN) ;

La procédure TABULATE

On notera dans cet exemple la factorisation dans la dimension cellule : là où on écrirait ACTUAL*MEAN PREDICT*MEAN, on peut raccourcir avec une mise en facteur commun et une paire de parenthèses. La logique est toute mathématique.

CLASS product country ;
VAR actual predict ;
TABLE (country),
      (product)*
      ((actual predict)
       * MEAN) ;

La procédure TABULATE

On rajoute, dans la dimension ligne, une seconde variable de classification, REGION.

Avec une étoile qui la sépare de COUNTRY et ALL, on va avoir le détail par pays et le récapitulatif tous pays confondus pour chaque valeur de REGION.

CLASS product country region ;
VAR actual ;
TABLE (region * (country ALL)),
      (product) *
      (actual * MEAN) ;

La procédure TABULATE

Si, par rapport au tableau précédent, on remplace l’étoile dans la dimension ligne par un espace, alors on a d’abord le détail par REGION, puis par COUNTRY, puis le récapitulatif. Avec l’étoile, le détail par COUNTRY était imbriqué dans celui par REGION.

PROC TABULATE DATA = sashelp.prdsale ;
 CLASS product country region ;
 VAR actual ;
 TABLE (region country ALL),
 (product)*
 (actual * MEAN) ;
 RUN ;

La procédure TABULATE

Ici, à cause des espaces entre les éléments de la dimension ligne, les deux lignes ALL de récapitulatifs sont identiques.

TABLE ((region ALL)
          (country ALL)),
      (product)*
      (actual * MEAN) ;

La procédure TABULATE

Même programme, hormis une étoile à la place de l’espace central dans la dimension ligne. Là, les deux ALL ont des portées différentes.

Le second récapitule les valeurs de COUNTRY à l’intérieur de l’imbrication REGION.

Le premier correspond à un récapitulatif de toutes les valeurs de REGION.

TABLE ((region ALL)*
          (country ALL)),
      (product)*
      (actual * MEAN) ;

la procédure TABULATE

 

 

Itinéraire bis : quelques mises en forme plus complexes

 

Maintenant que vous voyez bien la logique des espaces, des virgules et des étoiles, déstructurons un petit peu par rapport au schéma initial (lignes),(colonnes)*(cellules).

On peut en effet déplacer les éléments constitutifs des cellules à l’intérieur des dimensions lignes et colonnes, afin de changer leur emplacement dans le tableau. Cependant, il faut qu’au final l’étoile se retrouve entre les variables de calcul (celles de VAR) et leur statistique.

Ici, on « remonte » la statistique MEAN de manière à ne la voir apparaître qu’une fois, avant la variable en colonne PRODUCT.

PROC TABULATE
   DATA = sashelp.prdsale ;
   CLASS country product ;
   VAR actual predict ;
   TABLE (country),
         (MEAN*product) *
         (actual) ;
RUN ;

la procédure TABULATE

Ici, on remonte carrément le couple variable de calcul / statistique, de manière à éviter au maximum les répétitions. On mesure alors, pour SAS, tout l’intérêt d’avoir défini au préalable les rôles des variables avec VAR et CLASS, pour comprendre l’instruction TABLE correctement.

TABLE (country *
        (actual predict)),
      ((actual * MEAN) *
         product) ;

la procédure TABULATE

 

 

Avec deux variables de calcul (ou plus), il peut être intéressant de dupliquer des lignes et non des colonnes. Il suffit alors de déplacer les variables en question (ici, ACTUAL et PREDICT) dans la dimension ligne, en les imbriquant dans les variables de classification avec une étoile.

TABLE (country *
        (actual predict)),
      (product) *
      (MEAN) ;

la procédure TABULATE

Une variante du tableau précédent pour éviter les répétitions consiste, là encore, à remonter la statistique au-dessus de la variable de classification de la dimension colonne.

TABLE (country *
         (actual predict)),
      (MEAN) *
      (product) ;

la procédure TABULATE

Comment jouer sur l’ordre d’affichage des valeurs dans les variables de classification ? Par défaut, c’est l’ordre des valeurs non formatées qui sera suivi.

Le fait d’appliquer seulement un format à une variable n’influe donc en rien sur l’ordre d’affichage, comme le prouve l’exemple suivant.

PROC FORMAT ;
     VALUE $pays
           "CANADA" = "Canada"
           "U.S.A." = "Etats-Unis"
           "GERMANY" = "Allemagne"
 ;
 RUN ;
 PROC TABULATE DATA = sashelp.prdsale ;
      CLASS country product ;
      FORMAT country $pays. ;
      VAR actual ;
      TABLE (ALL country),
      ((MEAN * actual) *
      product) ;
RUN ;

la procédure TABULATE

 

L’option ORDER= (au niveau de l’instruction PROC TABULATE) permet de jouer réellement sur l’ordre d’affichage des valeurs des variables de CLASS.

On peut donner à cette option trois valeurs : INTERNAL (valeurs telles qu’elles sont stockées dans la table, par défaut), FORMATTED (ordonne selon les valeurs formatées) et DATA (valeurs dans l’ordre où elles apparaissent dans la table, sans considérations d’ordre alphabétique).

PROC TABULATE DATA = sashelp.prdsale ORDER = FORMATED ; CLASS country product ; FORMAT country $pays. ; VAR actual ; TABLE (ALL country),((MEAN * actual) * product) ; RUN ;

la procédure TABULATE

 

 

 

avec ORDER=INTERNAL (par défaut)

 

 

la procédure TABULATE

 

 

avec ORDER = FORMATED et le format $pays.

 

 

la procédure TABULATE

 

 

avec ORDER = DATA et une proc SORT préalable selon ACTUAL

 

 

 

 

Route ou autoroute ? Blocs BY et dimension page

 

On peut automatiquement produire toute une série de tableaux avec la procédure TABULATE, sans recourir aux macros ni aux copier/coller. Pour cela, deux solutions : l’instruction BY, qui nécessite un tri préalable des données, et la complexification (encore !) de l’instruction TABLE avec l’ajout d’une dimension page, qui, elle, ne nécessite pas de tri préalable.

Si la variable de la dimension page doit apparaître impérativement dans CLASS, celle d’un BY n’a pas besoin d’y figurer. La différence entre les deux solutions ne se mesure qu’en termes de disposition du titre indiquant de quelle sous-population on consulte le tableau.

PROC SORT DATA = sashelp.prdsale OUT = work.ventes ;
     BY region ;
RUN ;
/* solution avec un BY : tri préalable obligatoire */
PROC TABULATE DATA = work.ventes ;
     CLASS country product ;
     FORMAT country $pays. ;
     BY region ;
     VAR actual ;
     TABLE (country),(MEAN*actual*product) ;
RUN ;
/* solution avec une dimension PAGE */
PROC TABULATE DATA = sashelp.prdsale ;
     CLASS region country product ;
     FORMAT country $pays. ;
     VAR actual ;
     TABLE region, (country),(MEAN*actual*product) ;
RUN ;

la procédure TABULATE

la procédure TABULATE

 

 

 

 

 

avec une instruction BY

La procédure TABULATELa procédure TABULATE avec une dimension page

 

Echangeur autoroutier : gestion des croisements

 

Que se passe-t-il si les croisements de deux variables de classes dans une même dimension (ligne ou colonne) n’existent pas tous ?
Par défaut, la ligne ou la colonne correspondante n’est tout simplement pas générée.

PROC TABULATE DATA = sashelp.prdsale ;
     WHERE NOT (country = "CANADA"
            AND year = 1994) ;
     CLASS year country product ;
     VAR actual ;
     TABLE (year*country),(actual*MEAN*product) ;
RUN ;

Pour illustrer le comportement par défaut de la procedure TABULATE, on élimine du traitement, par un WHERE, le croisement de l’année 1994 et du Canada. La ligne correspondante n’est pas affichée dans le tableau.

la procédure TABULATE

L’option PRINTMISS à la fin de l’instruction TABLE, après un slash /, permet de faire figurer tous les croisements dans le tableau, même ceux pour lesquels il n’y a pas d’observations valides à traiter.

TABLE (year*country),
      (actual*MEAN*product) /
              PRINTMISS ;

la procédure TABULATE

Une autre option permet de faire figurer dans un tableau des valeurs qui ne font pas l’objet d’observations dans la table lue : PRELOADFMT, qui s’ajoute à l’instruction CLASS après un slash.

En présence de cette option, la procédure TABULATE se base sur les formats utilisateurs associés aux variables de classification pour connaître les valeurs, et non sur le contenu de la table SAS. Cette option doit être associée à PRINTMISS pour pouvoir en constater les effets dans le tableau.

PROC FORMAT ;
     VALUE $pays
           "CANADA" = "Canada"
           "U.S.A." = "Etats-Unis"
           "GERMANY" = "Allemagne"
           "SPAIN" = "Espagne"
 ;
 RUN ;
 PROC TABULATE DATA = sashelp.prdsale ;
      CLASS country product
                    / PRELOADFMT ;
      FORMAT country $pays. ;
      VAR actual ;
      TABLE (country),
            (actual*MEAN*product)
             / PRINTMISS ;
RUN ;

Dans cet exemple, on ajoute un pays au format, qui n’existe pas dans les données.
Grâce à PRELOADFMT et PRINTMISS, il est néanmoins présent dans le tableau.

la procédure TABULATE

 

Dos d’âne : modification de labels et de formats

 

Jusqu’à présent, hormis l’application d’un format à une variable de classification, nous avons accepté tels quels les choix de mise en forme de la procédure TABULATE. Cela ne peut plus durer ! Prenons en main nos labels, en-têtes, et formats de cellules !

Application d’un format aux cellules

Il est possible de changer l’affichage par défaut des nombres dans les cellules calculées du tableau ; pour cela, il faut ajouter derrière la statistique concernée une étoile, puis F= et le nom du format. Cela charge encore un peu la définition de l’instruction TABLE, mais le résultat est nettement plus élégant, surtout avec l’utilisation de formats comme NUMX (séparateur de décimales = virgule) et NLNUM en version 9 (séparateur de milliers = espace et séparateur de décimales = virgule, si on a spécifié OPTION LOCALE=FRENCH ; au préalable).

OPTION LOCALE = FRENCH ;
 PROC TABULATE DATA = sashelp.prdsale ;
      CLASS country ;
      VAR actual ;
      TABLE (country),
            (actual*
              (SUM*F=NLNUM12.1
               MEAN*F=NUMX12.2)) ;
RUN ;

la procédure TABULATE

Changements de libellés de cases

Pour changer l’intitulé d’une case contenant la valeur d’une variable de classification, il faut avoir recours à un format. En revanche, pour changer les autres intitulés (nom de statistique, labels de variables), il suffit de rajouter à côté de l’élément concerné, dans l’instruction TABLE, un signe = suivi, entre guillemets, du nouveau texte à afficher. Pour supprimer une case, il suffit de proposer comme nouveau texte un espace entre guillemets.

PROC TABULATE DATA = sashelp.prdsale ;
     WHERE product IN ("SOFA","CHAIR") ;
     CLASS country year ;
     VAR actual ;
     TABLE (country = "" ALL = "Total"),
           (actual = "Ventes réelles (total annuel)" *
            SUM = "" * F = NLNUM10.2 *
            year = "") ;
RUN ;

Par rapport à la version brute du tableau, on supprime les cases correspondant à SUM et aux labels des variables YEAR et COUNTRY. On modifie le libellé des cases correspondant au label de ACTUAL et au mot-clé ALL. Ces modifications de libellés sont totalement compatibles avec des changements de formats des cellules. Ici, on leur applique le format NLNUM avec 2 décimales.

la procédure TABULATE

La case supérieure gauche

Pour le moment, la case supérieure gauche du tableau a été laissée en jachère. On contrôle son contenu avec l’option BOX, qui est à préciser à la fin de l’instruction TABLE, après un slash, comme l’option PRINTMISS déjà évoquée.

Derrière BOX, comme pour les autres éléments de l’instruction TABLE, on ajoute un signe = et, entre guillemets, le texte de remplacement. On peut également, après le signe =, donner sans guillemets le nom d’une variable : c’est alors son label qui sera affiché dans la case supérieure gauche.

Enfin, on peut utiliser le mot-clé _PAGE_ qui correspondra à la valeur courante de la variable de page (voir plus haut).

TABLE (country = "" ALL = "Total"),
      (actual = "Ventes réelles ($US)" *
       SUM = "" * F = NLNUM10.2)
            / BOX = country ;

On intègre facilement, le label de la variable en ligne COUNTRY, non pas comme une 1ère ligne dans le tableau (éditée par défaut, mais supprimée par = » « ), mais dans la case supérieure gauche avec BOX.

la procédure TABULATE

PROC TABULATE DATA = sashelp.prdsale ;
     CLASS product country ;
     VAR actual predict ;
     TABLE product,
     country="",
     (actual predict) * SUM ="" / BOX = _PAGE_ ;
RUN ;

Ici, c’est la valeur de la variable de page, PRODUCT, qui est intégrée à la case supérieure gauche.

la procédure TABULATE

 

Utilisation de formats chevauchants

Comme dans la procédure MEANS, depuis la version 8 de SAS, il est possible d’utiliser dans TABULATE des formats chevauchants (multilabel) sur les variables de classification. Pour en appliquer aux variables de classification, il faut impérativement ajouter l’option MLF après un slash dans l’instruction CLASS, comme pour l’option PRELOADFMT déjà évoquée.

PROC FORMAT ;
     VALUE $paysmult (MULTILABEL)
           "CANADA","U.S.A." = "-- Amérique du Nord"
           "CANADA" = "Canada"
           "U.S.A." = "Etats-Unis"
           "GERMANY" = "-- Europe"
           "GERMANY" = "Allemagne" ;
RUN ;
 PROC TABULATE DATA = sashelp.prdsale ;
      CLASS country / MLF ; FORMAT country $paysmult. ;
      VAR actual ;
      TABLE (country = "" ALL = "Total"),
            (actual = "Ventes réelles ($US)" *
            SUM = "" * F = NLNUM10.2)
            / BOX = "Pays/région" ;
RUN ;

On regroupe les pays en deux grandes zones (Amérique du Nord et Europe), qu’on met en tête des lignes en commençant leurs libellés par des tirets. Ces groupes sont ensuite subdivisés par pays. Le format MULTILABEL permet de faire cela sans nécessité de dupliquer la variable COUNTRY et de lui appliquer deux formats différents : sur une grosse table, on économise en temps de traitement et en mémoire requise.

la procédure TABULATE

 

Faire le niveau d’huile (de coude) : mise en forme pour l’ODS

 

Dernière coquetterie que l’on peut ajouter à la procédure TABULATE, si on prévoit de récupérer les tableaux résultats dans un document externe à SAS (Word, PDF, Excel, HTML) via l’ODS : on peut préciser toute une série d’options de mise en forme. Elles sont repérées par un mot-clé, STYLE, derrière lequel on retrouvera un signe = et, entre crochets (!) les options et leurs valeurs. On peut ainsi avoir barre sur les polices, les couleurs, les alignements, la prise en compte des espaces à gauche d’une valeur, etc.

la procédure TABULATE

Pour l’élément de style BACKGROUND, outre des couleurs on peut également utiliser le mot-clé TRANSPARENT sans guillemets comme valeur.

L’emplacement de ces instructions de mise en forme dépend étroitement de l’emplacement de la cellule à « décorer » :

• en option après un slash dans une instruction CLASS s’il s’agit d’une cellule contenant un label de variable de classification ;

• en option après un slash dans une instruction CLASSLEV avec le nom de la variable en question s’il s’agit d’une cellule contenant les valeurs d’une variable de classification ;

• en option après un slash dans une instruction VAR s’il s’agit d’une cellule contenant un label de variable de calcul ;

• en option après un slash dans une instruction KEYWORD suivie du mot-clé statistique s’il s’agit d’une cellule contenant un nom de statistique ;

• à la suite du mot-clé statistique dans une instruction TABLE, avec une étoile puis, entre crochets, S=[instructions de mise en forme] ;

• pour l’option BOX (case en haut à gauche), la syntaxe BOX= »texte » devient BOX=[LABEL= »texte » STYLE=[instructions de mise en forme]].

 

La grande hétérogénéité de cette syntaxe impose qu’on l’illustre par l’exemple…

PROC TABULATE DATA = sashelp.prdsale ;
     CLASS country ;
     CLASSLEV country / STYLE=[FONT_STYLE=ITALIC] ;
     VAR actual / STYLE=[JUST=LEFT] ;
     TABLE (country = ""),
           (actual = "Ventes réelles" *
            SUM = "" * F=NLNUM10.2) *
                [STYLE = [foreground=WHITE
                          background=BLACK]] ;
RUN ;

la procédure TABULATE

Tableau de base

la procédure TABULATE

 

Avec les options de style du programme ci-dessus

35 found this helpful