Posts Tagged ‘count’

h1

Protégé : Newsletter Exercices – n°1 : Solution

juillet 14, 2012

Cet article est protégé par un mot de passe. Pour le lire, veuillez saisir votre mot de passe ci-dessous :

h1

Une petite histoire de macro : compter le nombre de mots dans un paramètre de macro

avril 11, 2010

Il est courant de devoir compter le nombre de mots dans un paramètre de macro. Il est par exemple possible de vouloir créer une boucle pour travailler chacun des termes contenu dans cette macro de manière séparée.

Voici donc l’histoire d’une mini macro qu’on nommera CNT_WRD qui crée une macro variable TOT_WRD renvoyant le nombre de mots contenu dans le paramètre TXT.

Ceci est pour vous l’occasion de voir ou revoir un raisonnement possible dans la construction d’une macro sous SAS.

1. Préciser ses besoins, une rapide « spécification »

La macro CNT_WRD composée d’un seul paramètre retournera dans une macro variable TOT_WRD le nombre de mots contenus dans le texte donné dans le paramètre de macro.

Ici on considérera comme mot, tout terme séparé par au moins un blanc.

Si le paramètre de macro est vide, la macro ne devra pas afficher de message d’erreur et la macro variable TOT_WRD sera égale à 1. Par défaut, aucune valeur ne sera entrée dans le paramètre TXT.

La macro variable doit pouvoir être utilisable à l’extérieur de la macro (macro variable globale).

2. Tester la fonction COUNT dans une étape data

La fonction COUNT permet de comptabiliser certains caractères et donc de répondre à ce type de besoin. En fait, cette fonction ne compte pas le nombre de mots mais compte le nombre de caractères définis par le second élément dans la fonction; dans notre cas, elle comptera le nombre de blancs. Il faut donc ajouter 1 au total.

Voici un exemple dans une étape data.

data _null_;
tot_wrd=1+count(‘mot1 mot2’,‘ ‘);
put tot_wrd=;
run;

Dans la log, vous pouvez voir que cnt_wrd=2.

Mais cela ne suffit pas pour gérer les blancs multiples et les blancs aux extrémités. Car si vous avez plus d’un blanc entre chaque mot, chacun sera compté. Il faut donc les enlever au préalable (avec la fonction COMPBL ici). Les blancs de début et fin peuvent s’enlever au moyen de la fonction STRIP.

data _null_;
tot_wrd=1+count(strip(compbl(‘ mot1 mot2 ‘)),‘ ‘);
put tot_wrd=;
run;

Mais que ce passe t-il si notre texte à compter est vide ? TOT_WRD sera égal à 1. Il faut donc ajouter le 1 au total que si le texte à analyser n’est pas vide.

data _null_;
length txt $200;
txt=;
if txt ne ‘ ‘ then tot_wrd=1+count(strip(compbl(txt)),‘ ‘);
put tot_wrd=;
run;

3. Créer la macro

Comme indiqué dans le dernier point, on travaille ici de manière conditionnelle. Si le paramètre de macro TXT est vide, la macro variable CNT_WRD nouvellement créée prend la valeur zéro. Sinon, On passe par la fonction COUNT.

Comme il n’existe pas d’équivalent aux fonctions COUNT et COMPBL en langage macro, il faut encadrer chacune d’elle dans une fonction macro SYSFUNC.

Ici on notera que la fonction STRIP n’apparaît pas. Les blancs de début et de fin en langage macro n’ont aucun impact.

%macro cnt_wrd(txt=);

%global tot_word;

%if &txt.= %then %let tot_wrd=0;
%else %let tot_wrd=%eval(1+%sysfunc(count(%sysfunc(compbl(&txt.)),%str( ))));

%mend cnt_wrd;

Pour représenter un blanc dans une étape data, il suffit d’utiliser des guillemets. En langage macro, on fait appel à la fonction %STR(). Il faudra ne pas oublier d’ajouter un blanc entre les parenthèses.

Afin d’ajouter 1 au résultat de la fonction COUNT, il faut utiliser la macro fonction %EVAL. Le contenu des macro variables sont sinon tous interprétés comme du texte, qu’il s’agisse de nombres ou pas.

Enfin, pour que cette macro variable TOT_WRD soit utilisable en dehors de la macro, il faut qu’elle soit globale. Hors par défaut, une macro variable créée dans une macro est locale, c’est-à-dire n’existe que le temps de la macro. L’instruction %GLOBAL TOT_WRD; résouds le problème.

4. Tester la macro dans le cadre de sa validation

Que se passe t-il quand on ne change pas la valeur par défaut du paramètre de macro ?

%cnt_wrd;
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand le paramètre de macro TXT est vide de texte ?
%put Valeur de TOT_WRD: &tot_wrd;

%cnt_wrd(txt=);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il lorsqu’il n’y a qu’un mot?

%cnt_wrd(txt=mot1);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand il y a plusieurs mots ?

%cnt_wrd(txt=mot1 mot2 mot3);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand il y a des blancs multiples entre les mots, en début et à la fin ?

%cnt_wrd(txt= mot1 mot2 mot3 );
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand il y a des blancs multiples entre les mots, en début et à la fin ?

%cnt_wrd(txt=mot1 mot2);
%put Valeur de TOT_WRD: &tot_wrd;

Que se passe t-il quand la macro est appelée plusieurs fois ?

%cnt_wrd(txt=mot1 mot2);
%put Valeur de TOT_WRD: &tot_wrd;
%cnt_wrd(txt=mot1);
%put Valeur de TOT_WRD: &tot_wrd;

Lecture complémentaire

h1

Combien d’observations dans mon data set ?

avril 14, 2008

Savoir trouver le nombre d’observations dans un data set SAS : tel est le sujet d’aujourd’hui. Connaître le nombre d’observations dans un jeu de données présente plusieurs avantages. En voici deux :

  • Définir une condition pour qu’un code soit exécuté.
  • Définir une boucle pour exécuter un code autant de fois qu’il y a d’observations dans le data set d’origine.

Dans les deux cas, on choisi ici de sauvegarder ce nombre dans une macro variable. Quelles sont les méthodes à disposition pour trouver ce nombre ? Je vous en propose d’en détailler six. Celles-ci fonctionnent également lorsque le data set est vide d’observations.

Exemples illustrés avec le data set ORIG : pour illustrer les différentes méthodes, j’utilise un jeu de données nommé ORIG ne contenant pas d’observations.

data orig;
x=1;

*if x=1 then output;
if x=1 then delete;
run;

L’instruction %PUT permet de voir la valeur de mes macro variables dans la LOG.

1. La fonction COUNT dans PROC SQL : la procédure SQL et sa fonction COUNT permettent de retrouver le nombre total d’observations dans le data set lu, si on n’utilise pas de GROUP BY. L’étoile signifie « TOUTES LES OBSERVATIONS », indépendamment de la variable. Si le nombre d’observations est stocké dans une variable, la valeur s’affiche pour chaque observation. Comme cette valeur est la même pour toutes les observations, on peut n’en afficher qu’une seule via DISTINCT. On peut sauvegarder cette information dans une macro variable via INTO:. Si le DISTINCT n’est pas utilisé, seule la première valeur sera sauvegardé dans la macro variable. DISTINCT est donc optionnel dans ce cas précis.

proc sql noprint;
select distinct count(*) into: methode1
from orig;
quit;

%put METHOD 1 = &methode1. ;


2. SQLOBS, une macro variable automatique à utiliser avec précaution : lorsqu’un data set est créé avec une procédure SQL, on peut, juste après, retrouver l’information avec la macro variable automatique &SQLOBS. Il faut bien faire attention de ne pas inclure d’autres data sets entre temps, lors d’une mise à jour par exemple. SQLOBS récupère le nombre d’observations du dernier jeu de données quelque soit son nom.

proc sql ;
create table methode2 as
select *
from orig;
quit;

%put METHODE 2 = &sqlobs. ;

3. Les métadonnées des dictionnaires SAS : le dictionnaire TABLES liste tous les data sets de toutes les bibliothèques et des informations supplémentaires les caractérisant. Ainsi la variable NOBS contient le nombre d’observations dans le data set. Ici on choisi INTO: pour sauvegarder ce nombre dans une macro variable.

proc sql noprint;
select nobs into: methode3
from dictionary.tables
where upcase(libname)=’WORK’ and
upcase(memname)=’ORIG’;
quit;

%put METHODE 3 = &methode3. ;

4. ATTRN comme « SAS Component Language » ou SCL : le SCL nommé ATTRN permet d’accéder au nombre d’observations. Pour cela, le nom du data set en question et le mot clé NOBS sont données. Ce SCL est accessible via %SYSFUNC. Pour lire le data set et extraire cette information, il faut au préalable, l’ouvrir et ensuite le fermer pour éviter des bugs, via les SCL OPEN et CLOSE. On réfère donc au data set via la macro variable DSID ouvrant le data set.

%let dsid     = %sysfunc(open(work.orig,in));
%let methode4 = %sysfunc(attrn(&dsid,nobs));
%if &dsid. > 0 %then %let rc = %sysfunc(close(&dsid));

%put METHODE 4 = &methode4. ;

5. La variable automatique _N_ : dans un data step, une variable nommée _N_ est créée automatique. Elle contient le nombre total d’itérations effectuées par SAS. Ainsi, si aucune donnée n’est lue, _N_=1. Une fois la lecture d’une observation faite par exemple, SAS revient juste après l’instruction DATA et _N_ est incrémenté de 1. Le nombre d’observations dans le data set est donc _N_-1. Ce nombre est sauvegardé ici dans une macro variable appelée METHODE5 créée via une instruction CALL SYMPUTX.

data_null_;
call symputx(‘methode5’,_N_-1);
set orig;
run;

%put METHODE 5 = &methode5. ;

6.  L’option NOBS de l’instruction SET : en précisant un nom après l’option NOBS= de l’instruction SET, la valeur de NOBS est sauvegardée dans une variable. Ici, elle s’appelle METHODE6. L’instruction CALL SYMPUTX permet de sauvegarder cette valeur dans une macro variable. La manière dont SAS traite le code est très importante ici.  Les explications d’Alain vous sont données plus bas.

data _null_;
if 0 then set orig nobs=methode6;
call symputx(‘methode6’,methode6);
stop;
run;

Le « IF 0 » est une instruction toujours fausse, donc l’exécution de l’instruction
conditionnée ne sera jamais réalisée. La récupération du nombre d’observations
depuis le dictionnaire du data set se fait au moment de la compilation par le SAS DATA
COMPILER, qui stocke dans une variable qui est forcément temporaire citée avec
l’option « NOBS= ».

L’instruction STOP ne permet pas d’écourter le temps de lecture des données car il
n’y pas d’exécution de lecture. Alors que se passe-t-il ?

L’étape DATA étant une boucle automatique dès qu’une instruction de lecture (Set ,
Merge, Modify, Update, …) de data set est détectée par le Superviseur SAS et par
compilateur de l’étape DATA , l’exécution de la boucle est automatique à cause de la
détection de l’instruction « SET » et SAS va vérifier si le test
induit par l’instruction « IF 0 » (comprendre if 0 =1) n’est pas devenu vrai !
D’où la nécessité de poser l’instruction SAS « STOP », pour éviter la boucle de
l’étape DATA.

 

(SUPERVISEUR SAS : Agent pivot qui distribue le code soumis par PARSING, soit au
DATASTEP COMPILER, PROCEDURE PARSER ou au Compilateur MACRO)

h1

Fini le Moyen-Age pour compter les mots

février 20, 2008

ulrepforte.jpg 

Vous avez une variable composée d’un ou plusieurs mots pour chaque observation, le tout séparé par des espaces, des virgules ou autre. Et vous voulez savoir combien il y a de mots. Avec SAS 9, il est très rapide de trouver le nombre de mots. Avec SAS 8.2, il faut pallier à l’absence de la fonction COUNT. Dans les deux cas, l’idée est la même : on compte les délimiteurs et on ajoute 1.

Prenons le cas des espaces. Dans un premier temps, on enlève les blancs de début et de fin de chaîne. Puis on enlève les doublons entre les mots. Enfin on compte les espaces restants. Il faudra aussi tenir compte du fait qu’une observation puisse ne contenir aucune valeur.

Voici les données qui serviront d’exemple :

data ds_orig;
   x=‘ AB CD GH ‘;
   output;
   x=‘ ‘;
   output;
   x=‘AB ‘;
   output;
run;

1. Avec SAS 9, un calcul rapide : il faudra faire appel à:

  • la fonction STRIP pour les blancs aux extrémités,
  • la fonction COMPBL pour enlever les blancs doublons,
  • la fonction COUNT  pour compter le nombre d’occurrence d’un caractère donné,
  • la fonction MISSING ou un simple = ‘ ‘ pour savoir si la chaîne est vide.

Voici un exemple avec des espaces pour délimiteur.

data sas9 ;
   set ds_orig;
   if x = ‘ ‘ then nb_mots = 0;
   else nb_mots=count(compbl(strip(x)),‘ ‘) + 1;
run;

2. Avec SAS 8.2, il faut contourner l’absence de la fonction COUNT: il existe plusieurs options dont celle-ci utilisant une boucle DO WHILE

  • Les fonctions TRIM et LEFT remplacent la fonction STRIP.
  • Les fonctions COMPLB et MISSING restent valide.
  • Une boucle remplacera la fonction COUNT.

On extrait le 1er mot de la chaîne, puis le 2nd, etc. via la fonction SCAN. Si la valeur trouvée est une valeur manquante, alors le nombre de mots est égal au nombre du boucles sans valeur manquante, c’est-à-dire le nombre de boucles actuel moins 1. Le compteur, ici nommé i, est réinitialisé pour arrêter la boucle DO WHILE.


data sas8_2;
   set ds_orig;
   if missing(x)then cnt_mots=0;
   else
      do;
         z=compbl(trim(left(x)));
         i=1;
         do until (i=0);
         if missing(scan(z,i,‘ ‘))then
            do;
               cnt_mots=i-1;i=->1;
               end;
               i=i+1;
            end;
         drop i z;
   end;
run;