📖 Cours - Module IV - Sélectionner et créer des variables
- Filtrer les colonnes avec KEEP et DROP, les lignes avec FIRSTOBS, OBS et WHERE
- Définir les attributs d'une variable avec ATTRIB ou LENGTH, FORMAT, INFORMAT, LABEL
- Utiliser les principales familles de fonctions SAS
- Convertir un type avec INPUT et PUT, décaler une série avec LAG et DIF
- Calculer une durée entre deux dates et déplacer une date avec INTCK et INTNX
1. Sélection de variables : KEEP et DROP
Il est possible de ne recopier que certaines variables de la table source. KEEP conserve, DROP supprime.
data TABLE_CREEE ;
set TABLE_LUE (keep = VAR1 VAR2) ;
run ;
data TABLE_CREEE ;
set TABLE_LUE (drop = VAR3 VAR4) ;
run ;
Les listes de variables sont séparées par des blancs, jamais par des virgules.
2. Sélection sur les lignes
Pour filtrer les observations m à n, on utilise les options FIRSTOBS= et OBS= de l'instruction SET.
data destination ;
set source (firstobs = M obs = N) ;
run ;
Si FIRSTOBS n'est pas précisée, la table est recopiée à partir de la première observation. Si OBS n'est pas précisée, elle est recopiée jusqu'à la dernière.
Pour sélectionner à partir d'une condition, on utilise l'option WHERE :
data TABLE_CREEE ;
set TABLE_INITIALE (where = (AGE = 11)) ;
run ;
data TABLE_CREEE ;
set TABLE_INITIALE (where = (AGE between 11 and 15 and WEIGHT > 60)) ;
run ;
data TABLE_CREEE ;
set TABLE_INITIALE (where = (NAME in ("Barbara", "Ronald"))) ;
run ;
3. Définir les attributs des variables
Lorsque l'on crée de nouvelles variables, il est prudent de définir explicitement leurs attributs. Sinon la variable n'a ni format, ni informat, ni libellé, et sa longueur est celle par défaut.
Deux syntaxes équivalentes existent. L'instruction ATTRIB :
data TABLE_CREEE ;
set TABLE_INITIALE ;
attrib VARIABLE1 length = $24
format = DATE9.
informat = DDMMYY10.
label = "Libelle de la variable" ;
run ;
Ou les instructions séparées LENGTH, FORMAT, INFORMAT et LABEL :
data TABLE_CREEE ;
set TABLE_INITIALE ;
length VAR1 $24 VAR2 8 ;
format VAR1 $24. VAR2 DATE9. ;
informat VAR2 DDMMYY10. ;
label VAR1 = "Nom du client" VAR2 = "Date de vente" ;
run ;
Pour renommer une variable :
data TABLE_CREEE ;
set TABLE_INITIALE ;
rename ancien_nom = nouveau_nom ;
run ;
4. Les fonctions de manipulation de chaînes
| Fonction | Effet |
|---|---|
| Length(x) | Retourne la longueur de x |
| Compress(x,'c') | Compresse x en enlevant les caractères c |
| Repeat(x,n) | Forme une chaîne qui est n fois la répétition de x |
| Index(x,y) | Retourne la position du début du mot y dans x |
| Upcase(x) / Lowcase(x) | Met x en majuscules / en minuscules |
| Dequote(x) / Quote(x) | Enlève / ajoute les guillemets |
| Substr(x,n,l) | Extrait de x un mot de longueur l à partir du nième caractère |
| Scan(x,n,'sp') | Extrait de x le nième mot, sp étant le séparateur |
| Tranwrd(x,y,z) | Remplace dans x toutes les occurrences de y par z |
| x || y | Concaténation de deux chaînes |
5. Les fonctions de manipulation de dates
| Fonction | Effet |
|---|---|
| mdy(m,j,a) | Crée une date de jour j, mois m et année a |
| Date() | Retourne la date courante |
| Datetime() | Retourne la date et l'heure courantes |
| Datepart(d) | Extrait la partie date d'un datetime |
| Day(d) / Month(d) / Year(d) | Retourne le jour / le mois / l'année d'une date |
| Weekday(d) | Retourne le jour de la semaine d'une date |
Deux fonctions supplémentaires méritent une place à part, car elles ne raisonnent pas en nombre de jours mais en intervalles de calendrier (mois, trimestre, année) : INTCK compte le nombre d'intervalles entiers entre deux dates, et INTNX déplace une date d'un certain nombre d'intervalles.
INTCK('interval', date_debut, date_fin) /* nombre d'intervalles entre les deux dates */
INTNX('interval', date, n) /* date avancee de n intervalles */
| Intervalle | Signification |
|---|---|
| 'day' | Jour |
| 'week' | Semaine |
| 'month' | Mois |
| 'qtr' | Trimestre |
| 'year' | Année |
data _null_ ;
d1 = mdy(1, 15, 2024) ;
d2 = mdy(6, 20, 2024) ;
nb_mois = intck('month', d1, d2) ;
put nb_mois= ;
d3 = intnx('month', d1, 3) ;
put d3 date9. ;
run ;
intck('month','31JAN2024'd,'01FEB2024'd) vaut déjà 1, alors qu'un seul jour s'est écoulé, simplement parce qu'on est passé de janvier à février. C'est le piège le plus fréquent avec cette fonction.6. Fonctions mathématiques, statistiques et aléatoires
| Fonction | Effet |
|---|---|
| Floor(x) / Abs(x) / Sign(x) | Partie entière / valeur absolue / signe de x |
| Round(x,a) | Arrondit x à la précision a |
| Max(x1,...,xn) / Min(x1,...,xn) | Maximum / minimum des valeurs |
| Mod(x,y) | Reste de la division euclidienne de x par y |
| Sqrt(x) / Exp(x) / Log(x) | Racine carrée / exponentielle / logarithme népérien |
| n(x1,...,xn) / nmiss(x1,...,xn) | Nombre de valeurs non manquantes / manquantes |
| sum / mean / var | Somme, moyenne, variance empirique des variables citées |
| Rannor(a) / Ranuni(a) | Tirage selon une loi normale centrée réduite / uniforme sur [0,1] |
| Ranpoi(a,l) / Ranbin(a,n,p) | Tirage selon une loi de Poisson / binomiale |
| Probnorm(t) / Probchi(t,n) / Probf(t,n,p) | Fonctions de répartition en t des lois correspondantes |
7. Les fonctions particulières : INPUT, PUT, LAG, DIF
| Fonction | Effet |
|---|---|
| Input(vchar, format) | Transforme une variable caractère en variable numérique |
| Put(vnum, format) | Transforme une variable numérique en variable caractère |
| Lagn(x) | Retourne la valeur n fois précédente de x ; pour n=1 on note Lag(x) |
| Difn(x) | Retourne x - Lagn(x) ; pour n=1 on note Dif(x) |
/* Caractere vers numerique */ age_num = input(age_char, 3.) ; /* Numerique vers caractere */ age_char = put(age_num, 3.) ; /* Valeur precedente et variation */ prec = lag(WEIGHT) ; var = dif(WEIGHT) ;
8. Exercices d'application
Voir le corrigé
data work.class1 ;
set sashelp.class (keep = name age) ;
run ;
data work.class2 ;
set sashelp.class (drop = sex weight height) ;
run ;
Voir le corrigé
data work.class3 ;
set sashelp.class (firstobs = 8 obs = 16) ;
run ;
Dans l'ordre par défaut de SASHELP.CLASS, Janet est la 8e observation et Robert la 16e : c'est une application directe de FIRSTOBS/OBS vue en section 2, plus rapide ici qu'un filtre WHERE sur le nom.
Voir le corrigé
data work.a ;
set sashelp.class (where = (age = 11)) ;
run ;
data work.b ;
set sashelp.class (where = (age = 11) keep = name age) ;
run ;
data work.c ;
set sashelp.class (where = (age between 11 and 15 and weight > 60)) ;
run ;
data work.d ;
set sashelp.class (where = (name in ("Barbara", "Ronald"))) ;
run ;
Voir le corrigé
data work.class4 ;
set sashelp.class ;
abrev = substr(name, 1, 3) ;
height_cm = height * 2.54 ;
run ;
Voir le corrigé
data work.class5 ;
set sashelp.class (where = (substr(name,1,2) = "Ja")) ;
name_y = tranwrd(name, "a", "Y") ;
run ;
Voir le corrigé
data work.class6 ;
set sashelp.class ;
personne = "M-" || name ;
caracteristiques = "age : " || put(age,3.) || " - taille : " || put(height,4.1)
|| " - poids : " || put(weight,5.1) ;
run ;
La concaténation avec
|| exige des chaînes de caractères des deux côtés : c'est pourquoi AGE, HEIGHT et WEIGHT, qui sont numériques, doivent d'abord passer par PUT.Voir le corrigé
data work.class7 ;
set sashelp.class ;
avant1 = lag(weight) ;
avant6 = lag6(weight) ;
run ;
Les six premières observations n'ont pas de 6e valeur précédente : AVANT6 y est manquant, ce qui est normal.
Voir le corrigé
data work.mesdates2 ;
set mesdates ;
jour = day(ma_date) ;
mois = month(ma_date) ;
annee = year(ma_date) ;
date_time = datetime() ;
format date_time datetime19. ;
date_jour = date() ;
format date_jour date9. ;
ecart = date_fin - date_debut ;
date_plus1 = ma_date + 1 ;
format date_plus1 date9. ;
run ;
Adaptez ma_date, date_debut, date_fin aux noms réels des variables de votre table MESDATES. Ajouter 1 à une date SAS avance d'un jour, exactement comme ajouter 1 à un entier : c'est tout l'intérêt du stockage en nombre de jours.
Voir le corrigé
data work.contrat ;
debut = mdy(3, 15, 2022) ;
fin = mdy(11, 2, 2024) ;
format debut fin date9. ;
anciennete_mois = intck('month', debut, fin) ;
prochain_anniv = intnx('month', debut, anciennete_mois + 1) ;
format prochain_anniv date9. ;
run ;
ANCIENNETE_MOIS compte le nombre de mois calendaires pleinement franchis depuis le début du contrat. PROCHAIN_ANNIV réutilise directement ce résultat : on avance la date de début d'un mois de plus que l'ancienneté déjà acquise, ce qui donne l'anniversaire mensuel suivant sans avoir à raisonner en jours.
- QCM — QCM Module IV — 6 questions, auto-évaluation
Couleur de fond
Police
Crénage de la police
Visibilité de l’image
Hauteur de ligne
Surbrillance de lien
Alignement du texte
Taille de police
Espacement des lettres
Couleur de texte
Largeur de paragraphe