SAS Base  •  Module IV  •  2 h
Sélectionner et créer des variables
M2 TIDE — Stage de programmation SAS — Enseignement 100 % distanciel
Objectifs du module
  • 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.

Placer KEEP ou DROP en option de SET (à la lecture) plutôt qu'en option de DATA (à l'écriture) évite de charger inutilement les colonnes en mémoire. Sur une table volumineuse, la différence de temps d'exécution est très nette. Nous y reviendrons dans les bonnes pratiques du module VII.

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 compte les changements de calendrier traversés, pas le nombre exact de jours écoulés divisé par la durée moyenne de l'intervalle : 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)
INPUT et PUT sont sources de confusion permanente. Moyen mnémotechnique : INPUT fait entrer du texte dans le monde numérique, PUT pose du numérique dans le monde texte. Le format passé en second argument décrit toujours la forme texte de la valeur.
/* 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

Exercice IV.1 — À partir de SASHELP.CLASS, créer WORK.CLASS1 en ne conservant que NAME et AGE, puis WORK.CLASS2 en supprimant SEX, WEIGHT et HEIGHT.
Voir le corrigé
data work.class1 ;
    set sashelp.class (keep = name age) ;
run ;

data work.class2 ;
    set sashelp.class (drop = sex weight height) ;
run ;
Exercice IV.2 — Créer WORK.CLASS3 avec les observations situées entre Janet et Robert inclus.
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.
Exercice IV.3 — Sélectionner les élèves de 11 ans ; puis les mêmes en ne conservant que NAME et AGE ; puis les personnes de 11 à 15 ans pesant strictement plus de 60 livres ; puis celles dont le nom est Barbara ou Ronald.
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 ;
Exercice IV.4 — À partir de SASHELP.CLASS, créer ABREV contenant les 3 premières lettres du nom, et HEIGHT_CM calculant la taille en centimètres.
Voir le corrigé
data work.class4 ;
    set sashelp.class ;
    abrev = substr(name, 1, 3) ;
    height_cm = height * 2.54 ;
run ;
Exercice IV.5 — Sélectionner les personnes dont le nom commence par « Ja » et créer une variable transformant tous les « a » de NAME en « Y » majuscule.
Voir le corrigé
data work.class5 ;
    set sashelp.class (where = (substr(name,1,2) = "Ja")) ;
    name_y = tranwrd(name, "a", "Y") ;
run ;
Exercice IV.6 — Créer PERSONNE dont la première occurrence sera M-Alfred, et CARACTERISTIQUES dont la première occurrence sera : age : 14 - taille : 69 - poids : 112,5.
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.
Exercice IV.7 — Créer AVANT1 retournant la valeur précédente de WEIGHT, et AVANT6 la sixième valeur précédente.
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.
Exercice IV.8 — À partir de la table MESDATES : créer JOUR, MOIS et ANNEE ; créer DATE_TIME au format datetime contenant la date et l'heure courantes ; créer DATE_JOUR contenant la date courante ; calculer l'écart en jours entre deux dates ; ajouter un jour à une date.
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.
Exercice IV.9 — À partir de deux dates de début et de fin de contrat (par exemple 15/03/2022 et 02/11/2024), calculer le nombre de mois pleins d'ancienneté avec INTCK, puis calculer la date exacte du prochain anniversaire de contrat avec INTNX.
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.
Point de contrôle — à faire avant de continuer
Testez ceci : créez une variable caractère contenant "0075" puis convertissez-la en numérique avec INPUT, et reconvertissez-la en caractère avec PUT au format 4. Que devient le zéro initial, et pourquoi ? La réponse conditionne la façon dont vous traiterez tout identifiant codé sur des chiffres.
Pour valider ce module
  • QCM — QCM Module IV — 6 questions, auto-évaluation
Last modified: Tuesday, 11 August 2026, 2:14 PM
Accessibility

Background Colour Background Colour

Font Face Font Face

Font Kerning Font Kerning

Image Visibility Image Visibility

Line Height Line Height

1.2

Link Highlight Link Highlight

Text Alignment Text Alignment

Font Size Font Size

1

Letter Spacing Letter Spacing

0

Text Colour Text Colour

Paragraph Width Paragraph Width

0