Dans les précédents articles sur cette série traitant du calcul de totaux, la procédure PROC SQL, le RETAIN dans une étape DATA et la procédure PROC MEANS nous on montré qu’elles pouvaient retrouver le nombre total de contrats pour chaque type (contrats téléphoniques, contrats d’habitation). La procédure PROC FREQ mérite également votre attention . Comme PROC MEANS, cette procédure utilise la notion de coefficient/poid (weight).
Rappel : Vous pouvez retrouver l’étape data créant le data set pour ce sujet en fin d’article. Les données contiennent l’identifiant du client CLIENT, le nombre de contrats NB_CNTR et deux variables binaires TEL et HABITAT indiquant si oui ou non les fréquences s’appliquent. Au total, on compte 9 contrats téléphoniques et 5 contrats d’habitation.
client nb_cntr tel habitat;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
1. Deux approches possibles
Avec la procédure PROC FREQ, deux options s’offrent à vous :
- D’abord générer un data set par type de contrat avec PROC FREQ et ensuite combiner les données.
- D’abord changer la structure des données et ensuite obtenir un seul data set avec PROC FREQ.
Par soucis de simplicité, je vous propose d’aborder la seconde méthode qui me semble de loin la plus logique pour nos données.
Etape 1 : Changer la structure des données revient à avoir d’un côté le nom des différents types de contrats et de l’autre si oui ou non une fréquence s’applique pour eux. Il n’y a alors plus qu’une seule variable binaire.
Pour changer cette structure des données, deux solutions sont possibles :
- une étape data ou
- la procédure PROC TRANSPOSE.
La première approche servira à comprendre la manipulation. La seconde approche est facilement généralisable à un plus grand nombre de variable et a donc ma préférence.
Etape 2 : Pour extraire le data set avec PROC FREQ, il existe l’ancienne méthode avec l’option OUT= et la nouvelle beaucoup plus standard ODS OUTPUT. Le raisonnement appliqué par cette méthode est applicable à de nombreuses procédure. La syntaxe est donc beaucoup facile de la retenir.
2. Etape 1 – Changer la structure des données en utilisant une étape data
Il s’agit de créer une variable unique indiquant si oui ou non les coefficients (weight) données dans la variable NB_CNTR s’appliquent.
data contrats_update ;
length contrat $7;
set contrats (in=a keep=nb_cntr tel rename=(tel=tmp) )
contrats ( keep=nb_cntr habitat rename=(habitat=tmp) );
if a then contrat='tel';
else contrat='habitat';
run;
Les 6 premières lignes sont consacrées au contrat de téléphone et les 6 dernières concernent les contrats d’habitation.
Seules les données où la variable binaire est oui (NO_YES=1) seront au final intéressante. Il est possible de supprimer les données où NO_YES=0 en ajoutant dans l’étape data un WHERE (where=(no_yes=1)) et en supprimant ensuite la variable NO_YES avec DROP (data contrats_update (drop=no_yes)). Voulant vous montrer les différentes étapes, je n’ai pas supprimé les lignes ou NO_YES=0.
nb_cntr no_yes contrat
5 1 tel
1 1 tel
2 0 tel
1 1 tel
3 0 tel
2 1 tel
5 0 habitat
1 0 habitat
2 1 habitat
1 0 habitat
3 1 habitat
2 0 habitat
3. Etape 1 alternative – chpour regrouper les contrats dans une seule variable : PROC TRANSPOSE
Pourquoi un PROC SORT ? Dans cette section, il est fait usage de la procédure PROC TRANSPOSE pour modifier la structure du data set de départ. Comme une instruction BY est nécessaire, il est obligatoire d’avoir au préalable les données triées dans ce même ordre. Ceci explique la présence actuelle de la procédure PROC SORT.
Pourquoi une option OUT= ? une Ne souhaitant pas ajouter ces changement dans le fichier d’origine, j’ai donné le nom CONTRATS_UPDATE au nouveau data set. C’est un choix personnel pour cet article en particulier. Il n’y a aucune raison pour immiter obligatoirement ce choix.
proc sort data=contrats out=contrats_update;
by client nb_cntr;
run;
L’objectif est d’avoir à présent autant de lignes que de type de contrats (2 lignes par client dans notre exemple). Pour chaque ligne est donné le nombre de contrats pouvant s’appliquer (variable NB_CONTR) et si oui ou nom ce nombre s’applique (variable NO_YES).
proc transpose data=contrats_transp
out=contrats_transp (drop=client
rename=(_name_=contrat col1=no_yes));
by client nb_cntr;
var tel habitat;
run;
Après avoir renommé les variables _NAME_ et COL1, nous retrouvons le même résultat que précédemment à l’exception de l’ordre dans lequel sont triées les données. Mais cela n’a pas d’effet dans notre PROC FREQ à venir.
nb_cntr contrat no_yes
5 tel 1
5 habitat 0
1 tel 1
1 habitat 0
2 tel 0
2 habitat 1
1 tel 1
1 habitat 0
3 tel 0
3 habitat 1
2 tel 1
2 habitat 0
4. Etape 2 – Exécuter un PROC FREQ
ODS EXCLUDE ? Je souhaite créer un data set et seulement un data set. Hors par défaut le résultat (la sortie) est envoyé dans la fenêtre OUTPUT. L’instruction ODS EXCLUDE de début empêche cet envoi et celle de fin rétablit le statut initial.
ONEWAYFREQS ? Dans le cadre d’un tableau à une dimension, la sortie s’appelle ONEWAYFREQS. Un ODS TRACE ON/LISTING permet de retrouver lors d’une première exécution ce nom si vous avez oublié dans la fenêtre output (ODS TRACE OFF pour arrêter le processus).
ODS OUTPUT ? La sortie est envoyée dans le data set SOLUTION4 en se servant de l’instruction ODS OUTPUT et du nom de la sortie. Seules les variables CONTRAT et FREQUENCY sont conservées.
L’ancienne méthode ? En commentaire, vous trouverez l’option OUT= de l’instruction TAB qui vous fournira les mêmes statistiques. A noter que le nom de la variable pour les fréquences s’appelle cette fois COUNT et non plus FREQUENCY.
ods exclude onewayfreqs;
proc freq data=contrats_update (where=(no_yes=1));
weight nb_cntr;
by contrat;
table no_yes;
ods output onewayfreqs=solution4 (keep=contrat frequency);
*table tmp/out=solution4 (keep=contrat count);
run;
ods exclude none;
Au final, on retrouve bien 9 contrats téléphoniques et 5 contrats d’habitation.
contrat Frequency
tel 9
habitat 5
Annexe : entrer les données dans un tableau SAS
data contrats;
input client $ nb_cntr tel habitat;
datalines;
a 5 1 0
b 1 1 0
c 2 0 1
d 1 1 0
e 3 0 1
f 2 1 0
;
run;