logo

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

A partir de SAS 9.2, la procédure SGPLOT (et ses sœurs SGPANEL et SGSCATTER) vient proposer une autre manière de créer des graphiques depuis SAS. Cette présentation ne suppose aucune connaissance du fonctionnement « historique » de SAS/GRAPH. Quelqu’un qui n’a jamais utilisé une procédure GPLOT ou GCHART peut tout à fait comprendre la logique de SGPLOT, aussi bien qu’un familier de ces procédures (qui sera peut-être même dérouté par sa simplicité).

En SAS 9.3, les procédures SG… sont directement rattachées au module SAS Base, une manière de les présenter comme des outils de routine, indispensables tout autant qu’une procédure MEANS ou FREQ, ou qu’une étape DATA.

Cette documentation fait le point sur les fonctionnalités disponibles dès la version 9.2. Les données utilisées sont celles de la table SASHELP.PRDSALE disponible sur toutes les sessions SAS : on y décrit les ventes (prévues et réalisées) d’une entreprise en fonction des produits, des pays, des mois, etc.

 

L’organisation de cette présentation par l’exemple de la procédure SGPLOT est la suivante : d’abord une section sur le principe général de la procédure ; puis une consacrée aux graphiques sur données qualitatives ; suit une longue section sur la représentation des données quantitatives ; puis deux sections plus courtes sur les histogrammes et les boxplots.

Une image peinte en plusieurs couches

Le principe de la procédure SGPLOT est de bâtir le graphique final par une superposition d’éléments graphiques. Chaque élément graphique correspond à une instruction de la procédure. Le tableau ci-dessous reprend les principaux éléments en indiquant sommairement le type de graphique produit.

Par rapport à ces compatibilités limitées de SAS 9.2, les versions suivantes sont plus souples, mais des limitations demeurent. En revanche, les éléments de référence (axes, lignes, incrustations et légendes) sont compatibles avec tous les éléments du tableau précédent.

  • Instruction REFLINE : droite de référence horizontale ou verticale
  • Instruction INSET : encart de texte
  • Instruction KEYLEGEND : légende du graphique
  • Instructions XAXIS et YAXIS : gestion des axes primaires (bas et gauche respectivement)
  • Instructions X2AXIS et Y2AXIS : gestion des axes secondaires (haut et droite respectivement)

Pour obtenir un nuage de points et une droite de régression, on enchaîne dans la procédure SGPLOT des instructions SCATTER et REG. Si on veut incruster un texte dans le graphique, on ajoutera une instruction INSET aux précédentes. L’ordre d’énumération des éléments correspond à l’ordre d’empilement : la 1e citée se retrouve sous les autres, et n’est visible que par transparence. Il est donc important de ne pas finir par des instructions couvrant de larges portions du graphique, comme HISTOGRAM ou BAND, qui masqueraient d’autres éléments.

Des graphiques très discrets

Commençons par des exemples sur des données qualitatives. Les instructions possibles sont VBAR éventuellement accompagnée de VLINE, son symétrique HBAR + HLINE, ainsi que l’instruction DOT.

A noter que ces instructions se nourrissent de données de détail qui sont directement agrégées par la procédure. On peut évidemment proposer en entrée des données déjà compilées par une procédure statistique, mais ce n’est pas indispensable.

PROC SGPLOT DATA=sashelp.prdsale ;
  DOT product / STAT=SUM RESPONSE=actual ;
RUN ;

On souhaiterait probablement, par rapport à ce premier essai, avoir des points plus visibles.

PROC SGPLOT DATA=sashelp.prdsale ;
  DOT product / STAT=SUM RESPONSE=actual 
                MARKERATTRS=(SIZE=15);
RUN ;

On a modifié les attributs de style des marqueurs (option MARKERATTRS disponible dans toutes les instructions qui affichent des marqueurs) pour une taille plus élevée que le choix par défaut. On aurait également pu jouer sur la couleur ou le type de marqueur (sous-options COLOR et SYMBOL).

PROC SGPLOT DATA=sashelp.prdsale ;
  DOT product / STAT=SUM RESPONSE=actual
                MARKERATTRS=(SIZE=15 SYMBOL=SQUAREFILLED) ;
RUN ;

On peut ajouter à ces points des intervalles de confiance à condition de les positionner en fonction d’une moyenne et non d’une somme (option STAT=MEAN). On affichera au choix les deux extrémités de l’intervalle (option LIMITS=BOTH) ou uniquement l’une des 2 (valeurs LOWER et UPPER pour l’option LIMITS toujours).

Le calcul de ces intervalles de confiance est piloté par l’option LIMITSTAT qui vaut CLM (intervalle de confiance), STDDEV (on ajoute/retranche à la moyenne un certain nombre d’écarts-types) ou STDERR (on ajoute/retranche à la moyenne un certain nombre d’erreurs-types). Ces nombres sont indiqués dans l’option STDNUM.

PROC SGPLOT DATA=sashelp.prdsale ;
  DOT product / STAT=MEAN  RESPONSE=actual
                LIMITS=UPPER  LIMITSTAT=STDDEV
                NUMSTD=3
                MARKERATTRS=(SIZE=15  SYMBOL=SQUAREFILLED) ;
RUN ;

La superposition prend son intérêt si on souhaite avoir à la fois les ventes réalisées (variable ACTUAL) et les prédictions (PREDICT).

PROC SGPLOT DATA=sashelp.prdsale ;
  HBAR product / STAT=SUM   RESPONSE=predict ;
  DOT product  / STAT=SUM   RESPONSE=actual
         MARKERATTRS=(SYMBOL=SQUAREFILLED SIZE=15) ;
RUN ;

Le même graphique en permutant les instructions HBAR et DOT masque, pour le produit TABLE, les ventes réalisées sous la barre des prédictions.

PROC SGPLOT DATA=sashelp.prdsale ;
  DOT product  / STAT=SUM   RESPONSE=actual
         MARKERATTRS=(SYMBOL=SQUAREFILLED SIZE=15) ;
  HBAR product / STAT=SUM   RESPONSE=predict ; 
RUN ;

Dans l’instruction HBAR, on retrouve des options communes à toutes les instructions affichant des surfaces : TRANSPARENCY pour le degré de transparence des surfaces, et FILLATTRS pour les attributs de style du remplissage (principalement COLOR pour la couleur de remplissage).

PROC SGPLOT DATA=sashelp.prdsale ;
  HBAR product / STAT=SUM   RESPONSE=predict
                 TRANSPARENCY=.8 ;
  DOT product  / STAT=SUM   RESPONSE=actual
                 MARKERATTRS=(SYMBOL=SQUAREFILLED SIZE=15) ;
RUN ;

Si on souhaite se restreindre à l’année 1994 et l’indiquer sur le graphique, une première idée est d’ajouter une restriction (WHERE) aux données, et d’ajouter un texte (INSET) sur l’image produite.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year=1994)) ;
  HBAR product / STAT=SUM  RESPONSE=predict
                 TRANSPARENCY=.8 ;
  DOT product  / STAT=SUM  RESPONSE=actual
                 MARKERATTRS=(SYMBOL=SQUAREFILLED SIZE=15) ;
  INSET "Année 1994" / POSITION=BOTTOMLEFT NOBORDER ;
RUN ;

Cependant le résultat est un peu encombré, et notre texte est peu lisible. Il faudrait libérer un peu d’espace en bas de l’axe vertical pour que notre texte n’y entre pas en collision avec le reste du graphique. On va réussir cela avec l’instruction YAXIS puisqu’on veut modifier les caractéristiques de l’axe vertical. Le décalage (marge d’espace libre) de la 1e ou de la dernière marque sur cet axe se définit par les options OFFSETMAX et OFFSETMIN. Alors qu’intuitivement on irait modifier OFFSETMIN (on veut de l’espace en bas de l’axe), ici il faut jouer sur OFFSETMAX car vous aurez remarqué (ou pas) que l’axe d’un DOTPLOT est gradué du haut vers le bas (on le remarque à l’ordre alphabétique des produits) !

Rassurez-vous, DOTPLOT et HBAR sont les seuls éléments graphiques qui imposent ce type de gymnastique intellectuelle.

Les valeurs d’OFFSETMIN et OFFSETMAX sont en pourcentage de l’aire du graphique.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year=1994)) ;
  HBAR product / STAT=SUM  RESPONSE=predict  TRANSPARENCY=.8 ;
  DOT product  / STAT=SUM  RESPONSE=actual
                 MARKERATTRS=(SYMBOL=SQUAREFILLED SIZE=15) ;
  INSET "Année 1994" / POSITION=BOTTOMLEFT  NOBORDER ;
  YAXIS OFFSETMAX=.2 ;
RUN ;

Dans le texte d’un INSET, les conventions sont les suivantes : deux chaînes séparées par un signe égal sont justifiées respectivement à gauche et à droite dans l’encadré. S’il y a plusieurs chaînes consécutives qui ne sont pas séparées par des =, alors elles apparaissent à des lignes différentes.

On peut collecter les informations à afficher dans des macro-variables à l’avance, comme ici avec une procédure SQL.

PROC SQL NOPRINT ;
  SELECT SUM(actual) FORMAT=NLNUM7.,
         SUM(predict) FORMAT=NLNUM7.,
         (SUM(actual)-SUM(predict))/SUM(predict) FORMAT=NLPCTN12.
    INTO : act, : prd, : pct
  FROM sashelp.prdsale
  WHERE year=1994 ;
QUIT ;
PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year=1994)) ;
  HBAR product / STAT=SUM RESPONSE=predict
                 TRANSPARENCY=.8 ;
  INSET ("Total ventes"="&act"
         "Total prévisions"="&prd"
         "Ecart"=%SYSFUNC(COMPRESS("&pct"))
        ) / POSITION=TOPRIGHT NOBORDER ;
  YAXIS OFFSETMIN=.4 ;
RUN ;

Pour obtenir des bâtons et une courbe superposés, changeons légèrement de problématique et essayons de représenter l’évolution trimestrielle, en 1994, des ventes réelles et prédites. Un premier essai superpose des bâtons (VBAR) et une courbe (VLINE).

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year=1994)) ;
  VBAR quarter  / STAT=SUM RESPONSE=actual ;
  VLINE quarter / STAT=SUM RESPONSE=predict ;
  LABEL quarter = "Trimestre 1994" ;
RUN ;

Une première action à mener est d’éliminer la légende, qui prend beaucoup de place dans ce graphique. L’option NOAUTOLEGEND vient s’insérer au niveau de l’instruction PROC. Un format permettra également de regagner un peu de place pour les données.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year=1994))
            NOAUTOLEGEND ;
  VBAR quarter  / STAT=SUM RESPONSE=actual ;
  VLINE quarter / STAT=SUM RESPONSE=predict ;
  LABEL quarter = "Trimestre 1994" ;
  FORMAT actual NLNUM6. ;
RUN ;

La courbe manque encore de visibilité et on peut l’épaissir avec l’option LINEATTRS (commune à tous les éléments graphiques traçant des traits). Enfin, pour compenser l’absence de légende, on associe directement au niveau de la courbe une indication de sa nature avec l’option CURVELABEL.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year=1994))
            NOAUTOLEGEND ;
  VBAR quarter  / STAT=SUM RESPONSE=actual ;
  VLINE quarter / STAT=SUM RESPONSE=predict
                  LINEATTRS=(THICKNESS=3)  
                  CURVELABEL="Prédictions" ;
  LABEL quarter = "Trimestre 1994" ;
  FORMAT actual NLNUM6. ;
RUN ;

Une dernière possibilité pour représenter simultanément les ventes prédites et réelles est de superposer deux séries de barres. La 2e sera partiellement transparente (toujours l’option TRANSPARENCY) et n’occupera pas la même largeur : l’option BARWIDTH prend une option en pourcentage de la largeur par défaut des bâtons. Dans ce cas, le retour de la légende est plus que souhaitable : indispensable.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year = 1994)) ;
  VBAR quarter / STAT=SUM RESPONSE=actual ;
  VBAR quarter / STAT=SUM RESPONSE=predict
                 TRANSPARENCY=.5   BARWIDTH=.6 ;
  LABEL quarter = "Trimestre 1994" ;
  FORMAT actual NLNUM6. ;
RUN ;

Un dernier graphique avant de quitter les variables qualitatives : on peut utiliser les courbes VLINE et HLINE seules, sans obligation qu’elles soient superposées à des bâtons. On peut ainsi très aisément obtenir une évolution mensuelle des ventes réelles, à partir de données de détail que la procédure SGPLOT va résumer puis représenter par une courbe… en 3 lignes de code !

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(year = 1994)) ;
  VLINE month / RESPONSE=actual STAT=SUM ;
RUN ;

La tête dans les nuages (de points)

Pour les données quantitatives, nous allons commencer par agréger légèrement la table PRDSALE pour obtenir des données mensuelles de ventes cumulées (prévues et réelles) par produit.

PROC SUMMARY DATA=sashelp.prdsale ;
  VAR actual predict ;
  CLASS year month product ;
  WAYS 3 ;
  OUTPUT OUT=work.stats SUM= ;
RUN ;

Une fois les données résumées, on peut représenter les ventes mensuelles de tables.

PROC SGPLOT DATA=work.stats  (WHERE=(year = 1994 AND product="TABLE")) ;
  SCATTER X=month Y=actual ;
RUN ;

 

Dans ce graphique, le label sur l’axe horizontal est assez inutile puisqu’on devine aux valeurs qu’il s’agit de données temporelles. L’instruction XAXIS (son symétrique YAXIS fonctionne de même) comporte une option DISPLAY permettant d’éliminer une partie des éléments par défaut : NOLABEL, NOVALUE, NONE.

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994  AND product="TABLE")) ;
  SCATTER X=month Y=actual ;
  XAXIS DISPLAY=(NOLABEL) ;
RUN ;

La transformation en courbe n’est pas compliquée : on remplace le mot-clé SCATTER par SERIES, par STEP, par NEEDLE ou par LOESS selon l’allure de la courbe souhaitée.

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994 AND product="TABLE")) ;
  SERIES X=month Y=actual ;
RUN ;

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994 AND product="TABLE")) ;
  STEP X=month Y=actual ;
RUN ;

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994 AND product="TABLE")) ;
  NEEDLE X=month Y=actual ;
RUN ;

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994 AND product="TABLE")) ;
  LOESS X=month Y=actual ;
RUN ;

On peut évidemment faire apparaître à la fois les points et une courbe comme c’est automatiquement le cas pour les courbes lissées (LOESS, PBSPLINE). Il convient juste d’indiquer à la fois les instructions SCATTER et SERIES pour obtenir la superposition.

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994 AND product="TABLE")) ;
  SERIES X=month Y=actual ;
  SCATTER X=month Y=actual ;
RUN ;

Dans ce dernier cas, la légende automatique née de la superposition de deux éléments graphiques n’est pas souhaitable. On la désactivera avec NOAUTOLEGEND.

Mais qu’arrive-t-il si on veut montrer deux séries, pour les ventes de tables et de lits ? On utilisera l’option GROUP dans l’instruction SERIES (et dans SCATTER pour coordonner l’aspect des marqueurs et des courbes).

PROC SGPLOT DATA=work.stats (WHERE=(year = 1994 AND product IN ("BED", "TABLE"))) NOAUTOLEGEND ;
  SERIES X=month Y=actual  / GROUP=product ;
  SCATTER X=month Y=actual / GROUP=product ;
  XAXIS DISPLAY=(NOLABEL) ;
RUN ;

Dans ce nouveau graphique, comment savoir quelle courbe correspond aux tables, et laquelle aux chaises ? L’absence de légende est un souci, aussi nous allons imposer une légende personnalisée avec l’instruction KEYLEGEND. Pour nourrir celle-ci, il faut donner un nom (option NAME) aux éléments de graphique qui y figurent : si on se limite aux courbes, il suffit de nommer l’instruction SERIES. On reprend ensuite ce nom dans KEYLEGEND, avec des mentions de positionnement (dans le graphique ou en dehors, à quelle place) facultatives.

PROC SGPLOT DATA=work.stats  (WHERE=(year = 1994 AND product IN ("BED", "TABLE"))) NOAUTOLEGEND ;
  SERIES X=month Y=actual    / GROUP=product      NAME="courbe" ;
  SCATTER X=month Y=actual   / GROUP=product ;
  XAXIS DISPLAY=(NOLABEL) ;
  KEYLEGEND "courbe"        / POSITION=BOTTOMLEFT  LOCATION=INSIDE NOBORDER ;
RUN ;

Une autre solution, qui nécessiterait de transposer les données pour avoir une colonne « BED » et une colonne « TABLE », serait de faire plusieurs instructions SERIES, chacune dédiée à une courbe, dont le libellé serait directement inclus dans le graphique (toujours l’option CURVELABEL).

PROC TRANSPOSE DATA=work.stats (WHERE=(year = 1994 AND product IN ("BED","TABLE")))
                OUT=work.stats2 ;
  ID product ;
  BY year month ;
  VAR actual ;
RUN ;
PROC SGPLOT DATA=work.stats2 NOAUTOLEGEND ;
  SERIES X=month Y=bed       / CURVELABEL="Lits"   LINEATTRS=(COLOR=PURPLE) ;
  SERIES X=month Y=table     / CURVELABEL="Tables" LINEATTRS=(COLOR=ORANGE) ;
  SCATTER X=month Y=bed      / MARKERATTRS=(COLOR=PURPLE);
  SCATTER X=month Y=table    / MARKERATTRS=(COLOR=ORANGE);
RUN ;

En repartant d’une série simple, sur la table des statistiques transposée ou non, cherchons autre chose : à indiquer les valeurs associées à chaque point. L’option MARKERCHAR de SCATTER permet de remplacer les marqueurs par la valeur d’une variable (numérique ou texte). Avec un format personnalisé, nous afficherons les valeurs des ventes en milliers de $.

PROC FORMAT ;
  PICTURE kdollar (ROUND)
    0-HIGH = "0k$" (MULT=.001) ;
RUN ;
PROC SGPLOT DATA=work.stats2  NOAUTOLEGEND ;
  SERIES X=month Y=bed ;
  SCATTER X=month Y=bed  / MARKERCHAR=bed   MARKERCHARATTRS=(SIZE=6) ;
  FORMAT bed  kDollar. ;
  XAXIS DISPLAY=(NOLABEL NOTICKS) ;
RUN ;

Cependant ce graphique manque de lisibilité, car les montants affichés sont à cheval sur la courbe. Il faudrait les protéger dans un circle de fond blanc : on ajoute donc une instruction SCATTER, avec des marqueurs de type CIRCLEFILLED (disques) blancs. Et pour avoir un liseré autour de ces disques, un autre SCATTER avec un marqueur CIRCLEFILLED légèrement plus grand, dans la couleur par défaut.

PROC SGPLOT DATA=work.stats2 NOAUTOLEGEND ;
  SERIES X=month Y=bed ;
  SCATTER X=month Y=bed / MARKERATTRS=(SYMBOL=CIRCLEFILLED  SIZE=20) ;
  SCATTER X=month Y=bed / MARKERATTRS=(SYMBOL=CIRCLEFILLED  COLOR=WHITE   SIZE=17) ;
  SCATTER X=month Y=bed / MARKERCHAR=bed  MARKERCHARATTRS=(SIZE=6) ;
  FORMAT bed  kDollar. ;
  XAXIS DISPLAY=(NOLABEL NOTICKS) ;
RUN ;

La liste des marqueurs possibles est la suivante :

La superposition d’une courbe et d’une tendance (instruction REG) est, elle, beaucoup plus classique. On remarquera que les valeurs affichées sur l’axe horizontal sont automatiquement moins nombreuses puisque la place accordée pour le libellé « Tendance » tasse les valeurs de l’axe à gauche.

PROC SGPLOT DATA=work.stats2   NOAUTOLEGEND ;
  SERIES X=month Y=bed ;
  REG X=month Y=bed  / CURVELABEL="Tendance" ;
  XAXIS DISPLAY=(NOLABEL NOTICKS) ;
RUN ;

Plus costaud à visualiser, un mélange de tableau de données et de courbes sur le même graphique. Pour cela, on va utiliser SCATTER et son option magique MARKERCHAR pour produire le tableau de valeurs (ventes prédites ici), tandis qu’on jouera sur un second axe vertical, Y2, pour avoir ces données dans un espace laissé libre sous le graphique.

On va préparer les données selon un agrégat trimestriel de l’année 1994.

PROC SUMMARY DATA=sashelp.prdsale (WHERE=(year=1994
                                      AND product IN ("BED","TABLE"))) SUM ;
  VAR actual predict ;
  CLASS quarter product ;
  WAYS 2 ;
  OUTPUT OUT=work.stats_q SUM= ;
RUN ;
PROC SGPLOT DATA=work.stats_q  NOAUTOLEGEND ;
  SERIES X=quarter Y=actual     / GROUP=product NAME="s" ;
  SCATTER X=quarter Y=product   / MARKERCHAR=predict  Y2AXIS ;
  FORMAT quarter 1.    actual predict 5. ;
  KEYLEGEND "s" / NOBORDER TITLE="" ;
RUN ;

L’idée est là, mais les deux axes Y et Y2 se disputent l’intégralité de la hauteur du graphique. On va jouer sur leurs OFFSETMIN et OFFSETMAX pour libérer l’espace requis pour le tableau. Quant à l’axe des X, on lui ajoute l’option INTEGER afin de n’affiche que les valeurs entières de la variable trimestre (une graduation aux multiples de 0,5 ayant tendance à apparaître sur certaines versions du graphique).

PROC SGPLOT DATA=work.stats_q NOAUTOLEGEND ;
  SERIES X=quarter Y=actual     / GROUP=product NAME="s" ;
  SCATTER X=quarter Y=product   / MARKERCHAR=predict   Y2AXIS ;
  FORMAT quarter 1.  actual predict 5. ;
  KEYLEGEND "s" / NOBORDER TITLE=""  LOCATION=INSIDE ;
  YAXIS  OFFSETMAX=.2 ;
  Y2AXIS OFFSETMIN=.9
         DISPLAY=(NOTICKS NOLABEL) ;
  XAXIS DISPLAY=(NOLABEL) INTEGER ;
RUN ;

Restent que ces colonnes de donnée en tête de graphique sont quelque peu dépourvues de sens si elles n’ont pas de titre. Un INSET peut remédier à cela, à condition de lui laisser de la place avec encore un peu d’OFFSETMAX supplémentaire sur les deux axes verticaux.

PROC SGPLOT DATA=work.stats_q NOAUTOLEGEND ;
  SERIES X=quarter Y=actual     / GROUP=product NAME="s" ;
  SCATTER X=quarter Y=product   / MARKERCHAR=predict   Y2AXIS ;
  FORMAT quarter 1.  actual predict 5. ;
  KEYLEGEND "s" / NOBORDER TITLE=""  LOCATION=INSIDE 
                  POSITION=BOTTOMLEFT ;
  INSET "Ventes prévisionnelles" /  POSITION=TOP ;
  YAXIS  OFFSETMAX=.2 ;
  Y2AXIS OFFSETMIN=.8  OFFSETMAX=.14
         DISPLAY=(NOTICKS NOLABEL) ;
  XAXIS DISPLAY=(NOLABEL) INTEGER ;
RUN ;

Pour faire bande à part

L’ajout de zones colorées sur un graphique se fait avec l’instruction BAND. Sur nos données agrégées (ventes par mois en 1994 par produit), on souhaite présenter les ventes de lits, dans une zone colorée qui correspond aux ventes mensuelles du meilleur et du pire produit. On repart des données agrégées par produit, que l’on transpose et où l’on prépare le meilleur et le pire de chaque mois.

PROC SUMMARY DATA=sashelp.prdsale ;
  VAR actual predict ;
  CLASS year month product ; 
  WAYS 3 ;
  OUTPUT OUT=work.stats SUM= ;
RUN ;
PROC TRANSPOSE DATA=work.stats (WHERE=(year = 1994)) OUT=work.stats2 ;
  ID product ;
  BY year month ;
  VAR actual ;
RUN ;
DATA work.stats2 ;
  SET work.stats2 ;
  min = MIN(bed,chair,desk,sofa,table) ;
  max = MAX(bed,chair,desk,sofa,table) ;
RUN ;

Et maintenant les graphiques qu’on peut produire avec ces données.

PROC SGPLOT DATA=work.stats2 ;
  BAND X=month UPPER=max LOWER=min ;
  SERIES X=month Y=bed / CURVELABEL="Lits" ;
  XAXIS DISPLAY=(NOLABEL) ;
  YAXIS DISPLAY=(NOLABEL) ;
RUN ;

Si on utilise, pour tracer les ventes de lits, un graphique en escalier plutôt qu’une courbe classique, le résultat est étrange.

PROC SGPLOT DATA=work.stats2 ;
  BAND X=month UPPER=max LOWER=min / LEGENDLABEL="Ensemble des produits" ;
  STEP X=month Y=bed / LEGENDLABEL="Lits" ;
  XAXIS DISPLAY=(NOLABEL) TICKVALUEFORMAT=FRADFMN3. ;
  YAXIS DISPLAY=(NOLABEL) ;
RUN ;

On notera dans ce nouveau graphique des options inédites : LEGENDLABEL (qui est disponible dans la quasi-totalité des instructions graphiques) pour personnaliser l’entrée de la légende, ainsi que TICKVALUEFORMAT pour indiquer quel format s’applique aux valeurs d’un axe.

Pour synchroniser l’aspect des bandes et de la courbe en escalier, il est nécessaire de donner un nom à la courbe (option NAME) et d’utiliser ce nom dans l’option MODELNAME de l’instruction BAND.

PROC SGPLOT DATA=work.stats2 ;
  BAND X=month UPPER=max LOWER=min / MODELNAME="a" LEGENDLABEL="Ensemble des produits" ;
  STEP X=month Y=bed / NAME="a" LEGENDLABEL="Lits" ;
  XAXIS DISPLAY=(NOLABEL) TICKVALUEFORMAT=FRADFMN3. ;
  YAXIS DISPLAY=(NOLABEL) ;
RUN ;

Un peu de mise en boîte (à moustaches)

Commençons par des boîtes à moustaches simples : tout d’abord une seule, ce qui paraît si simple et s’avère si tortueux via la proc BOXPLOT.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(month="01jan1994"d)) ;
  VBOX actual ;
RUN ;

Détaillons ensuite : une boîte par produit vendu. Attention, ici l’option n’est pas GROUP comme pour les instructions SCATTER, REG, STEP, SERIES etc. mais CATEGORY.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(month="01jan1994"d)) ;
  VBOX actual / CATEGORY=product ;
RUN ;

On peut rajouter une incrustation de texte pour indiquer le mois représenté avec l’instruction INSET déjà vue. Une ligne de référence à 500$ se situera derrière ou devant les boîtes à moustaches, selon qu’on positionne l’instruction REFLINE avant ou après VBOX.

PROC SGPLOT DATA=sashelp.prdsale (WHERE=(month="01jan1994"d)) ;
  REFLINE 500 / AXIS=Y LABEL="500$" ;
  VBOX actual / CATEGORY=product ;
  INSET "Janvier 94" / POSITION=BOTTOMRIGHT NOBORDER ;
RUN ;

Histogrammes et courbes de densité

Terminons sur des graphiques en bâtons bâtis sur une variable quantitative : les histogrammes. La forme de base est très facile à obtenir.

PROC SGPLOT DATA=sashelp.prdsale ;
  HISTOGRAM actual ;
RUN ;

Si on le souhaite, on peut superposer à cet histogramme une courbe représentant au choix : soit une loi normale de mêmes moyenne et variance, soit une approximation empirique de la distribution (une version lissée de la courbe qui passerait par les sommets des barres). Pour cela, une seule instruction, DENSITY, avec une option TYPE qui vaut respectivement NORMAL ou KERNEL.

PROC SGPLOT DATA=sashelp.prdsale NOAUTOLEGEND ;
  HISTOGRAM actual ;
  DENSITY actual / TYPE=KERNEL ;
RUN ;

PROC SGPLOT DATA=sashelp.prdsale NOAUTOLEGEND ;
  HISTOGRAM actual ;
  DENSITY actual / TYPE=NORMAL ;
RUN ;

On peut évidemment superposer ces deux courbes en faisant deux instructions DENSITY. La superposition de deux histogrammes, elle, est rarement souhaitable. Dans le cas ci-dessous, où on compare la distribution des chiffres de vente pour les lits et des tables, les différences d’ordre de grandeur aboutissent à des barres de largeurs différentes, très déroutantes.

PROC SGPLOT DATA=work.STATS2 ;
  HISTOGRAM bed ;
  HISTOGRAM table / TRANSPARENCY=.5 ;
  XAXIS DISPLAY=(NOLABEL) ;
  KEYLEGEND / POSITION=TOPLEFT LOCATION=INSIDE DOWN=2 ;
  FORMAT bed table NLNUM6. ;
RUN ;

43 found this helpful