SAS Base  •  Module EB  •  Corrigé
Exercices de synthèse — SAS Base
M2 TIDE — Stage de programmation SAS — Enseignement 100 % distanciel
Objectifs du module
  • Mobiliser, sur des cas complets, l'ensemble des notions vues dans les modules I à VII
  • Enchaîner import, transformation, statistiques et graphiques sur un même jeu de données
  • Savoir repérer et corriger une anomalie de saisie à partir d'un graphique

Avant de commencer

Cette page contient le corrigé complet des exercices donnés en devoir à l'issue du bloc SAS Base (devoirs 1 à 6), réalisés en direct le vendredi 11 septembre entre 14h00 et 18h00. Elle reste masquée pendant que vous travaillez et n'est publiée qu'à la clôture du dépôt, à 18h00 : tant que vous n'avez pas déposé votre travail, vous ne devriez de toute façon pas pouvoir la consulter.

Chaque question dispose de son propre corrigé, replié par défaut. Dépliez-le pour vérifier votre réponse, comparer votre façon de faire, ou débloquer un point sur lequel vous étiez resté bloqué.

Exercice 1 — Prix des voitures d'occasion

On s'intéresse au prix de vente des voitures d'occasion et aux différents facteurs qui peuvent l'influencer. On travaille sur le fichier cars.txt, la description des données étant disponible dans cars-short-desc.txt.

Q1 — Importer le fichier des données dans une table SAS appelée cars. Formater les variables numériques : Price (2 décimales), Mileage (6 positions, 0 décimale), Cylinder (1 position), Liter (3 positions, 1 décimale), Doors, Cruise, Sound et Leather (1 position, 0 décimale).
Voir le corrigé
PROC IMPORT OUT = WORK.CARS
    DATAFILE = "/chemin/cars.txt"
    DBMS = TAB REPLACE ;
    GETNAMES = YES ;
RUN ;

data cars2 ;
    set cars ;
    format price 8.2  mileage 6.0  cylinder 1.0  liter 3.1
           doors 1.0  cruise 1.0  sound 1.0  leather 1.0 ;
run ;
Q2 — Transformer la variable contenant le nombre de miles en kilomètres (1 mile = 1,6 km).
Voir le corrigé
data cars2 ;
    set cars2 ;
    kilometrage = mileage * 1.6 ;
    drop mileage ;
run ;
Q3 — Représenter graphiquement les données en utilisant les variables de prix et de kilométrage. Qu'en déduisez-vous ?
Voir le corrigé
symbol1 i=none v=star c=red ;

proc gplot data=cars2 ;
    plot price*kilometrage = 1 ;
run ; quit ;

À première vue, le nuage de points ne montre aucun lien net entre le prix et le kilométrage. Mais en triant et en stratifiant l'analyse par marque, modèle et finition, la relation devient beaucoup plus nette :
proc sort data=cars2 ;
    by Make Model Trim ;
run ;

proc sgplot data=cars2 ;
    by Make ;
    reg y=Price x=Kilometrage ;
run ;

C'est une bonne illustration d'un principe général : un nuage de points global peut masquer une relation qui n'apparaît qu'une fois la population correctement stratifiée.
Q4 — Afficher les caractéristiques des voitures dont le prix est supérieur à 52 000 $. S'agit-il de valeurs aberrantes ? Que proposez-vous pour analyser le jeu de données ?
Voir le corrigé
proc print data=cars ;
    where price > 52000 ;
run ;

Il ne s'agit pas de valeurs aberrantes : ce sont des véhicules haut de gamme cohérents entre eux (cylindrée, équipement). La bonne approche, comme à la question 3, est d'analyser par marque et par modèle plutôt que sur la population entière.

Exercice 2 — Températures

Le fichier temperatures.txt contient 546 données mensuelles et quatre variables correspondant à l'année et au mois de chaque observation, ainsi qu'au niveau des précipitations (en mm) et à la température (en °C).

Q1 — Importer le fichier dans une table SAS temp.
Voir le corrigé
PROC IMPORT DATAFILE = "/chemin/temperatures.txt"
    OUT = WORK.TEMPERATURES DBMS = TAB REPLACE ;
RUN ;
Q2 — Formater les variables contenant le mois et l'année.
Voir le corrigé
data temp2 ;
    set temperatures ;
    format year 4.0  month z2. ;
    year = year + 1900 ;
run ;

Point important : dans ce fichier, l'année est codée sur deux chiffres (75 pour 1975). Aucun format ne peut deviner ce décalage à votre place : c'est une correction explicite (year = year + 1900) qu'il faut faire dans les données, pas seulement un affichage.
Q3 — Créer une variable date qui identifie chaque observation à l'aide de year et month (format d'affichage MMMYY).
Voir le corrigé
data temp3 ;
    set temp2 ;
    date = mdy(month, 1, year) ;
    format date monyy5. ;
run ;
Q4 — Afficher les valeurs des précipitations et des températures pour les dix premières observations.
Voir le corrigé
proc print data=temp3 (obs=10) ;
    var precp temp ;
    id date ;
run ;
Q5 — Créer la table tab1 avec la moyenne, l'écart-type, le maximum et le minimum des précipitations. Visualiser et afficher cette table.
Voir le corrigé
proc means data=temp3 noprint ;
    var precp ;
    output out=tab1 mean=m1 std=sigma max=maxi min=mini ;
run ;

proc print data=tab1 ; run ;
Q6 — Créer la table tab2 avec les moyennes annuelles des précipitations et des températures. Visualiser, afficher, puis tracer le graphe de ces moyennes.
Voir le corrigé
proc means data=temp3 noprint ;
    var temp precp ;
    class year ;
    output out=tab2 mean=m_temp m_precp ;
run ;

data tab2 ;
    set tab2 ;
    if _type_ = 0 then delete ;
    drop _type_ ;
run ;

proc print data=tab2 ;
    var m_temp m_precp ;
    id year ;
run ;

symbol1 i=join v=none c=black ;
symbol2 i=join v=none c=red ;

proc gplot data=tab2 ;
    plot m_temp*year=1 m_precp*year=2 / overlay ;
    title "Moyennes annuelles - temperatures et precipitations" ;
run ;

/* Avec deux echelles distinctes en ordonnee */
proc gplot data=tab2 ;
    plot  m_temp*year=1 ;
    plot2 m_precp*year=2 ;
run ;
title ;
Q7 — Même travail que Q6, mais avec la table tab3 et des moyennes mensuelles.
Voir le corrigé
proc means data=temp3 noprint ;
    var temp precp ;
    class month ;
    output out=tab3 mean=m_temp m_precp ;
run ;

data tab3 ;
    set tab3 ;
    if _type_ = 0 then delete ;
    drop _type_ ;
run ;

proc print data=tab3 ;
    var m_temp m_precp ;
    id month ;
run ;

proc gplot data=tab3 ;
    plot m_temp*month=1 m_precp*month=2 / overlay ;
    title "Moyennes mensuelles - temperatures et precipitations" ;
run ;

proc gplot data=tab3 ;
    plot  m_temp*month=1 ;
    plot2 m_precp*month=2 ;
run ;
title ; goptions reset=title ;

Exercice 3 — Pourboires

On étudie les facteurs qui pourraient influencer le montant des pourboires dans un restaurant, à partir du fichier tips.txt (description dans tips-short-desc.txt).

Q1 — Importer le fichier dans une table SAS tips.
Voir le corrigé
data tips ;
    infile "/chemin/tips.txt" ;
    input IDEN $ 1-4  TOTBILL 7-11  TIP 15-18  SEX 23-23
          SMOKER 30-30  DAY 35-35  TIME 40-40  SIZE 45-45 ;
run ;
Q2 — Créer une variable rate représentant le pourcentage du pourboire dans l'addition.
Voir le corrigé
data tips2 ;
    set tips ;
    rate = (tip*100) / totbill ;
    format rate 5.2 ;
run ;
Q3 — Calculer les statistiques descriptives (moyenne, écart-type, min, max) pour Totbill, Tip, Size et Rate. Commenter les résultats.
Voir le corrigé
proc means data=tips2 ;
    var totbill tip rate size ;
run ;
Q4 — Avec la PROC FORMAT, formater Day (3=Jeudi, 4=Vendredi, 5=Samedi, 6=Dimanche) et Time (0=Déjeuner, 1=Dîner).
Voir le corrigé
proc format ;
    value jour   3='Jeudi'  4='Vendredi'  5='Samedi'  6='Dimanche' ;
    value moment 0='Dejeuner'  1='Diner' ;
run ;

data tips3 ;
    set tips2 ;
    format day jour.  time moment. ;
run ;
Q5 — Calculer la moyenne des pourboires (valeur absolue et pourcentage) par jour et par moment de la journée.
Voir le corrigé
proc sort data=tips3 ;
    by day ;
run ;

proc means data=tips3 ;
    var rate ;
    by day ;
    class time ;
run ;
Q6 — Même question en séparant par sexe, fumeur/non-fumeur et nombre de personnes à table.
Voir le corrigé
proc sort data=tips3 ;
    by sex smoker ;
run ;

proc means data=tips3 ;
    var rate ;
    by sex smoker ;
    class size ;
run ;

Exercice 4 — Notes d'étudiants

Q1 — Construire la table temporaire notes avec les colonnes Nom, Interro1, Interro2, Interro3, pour Eric (12, 3, 8), Maxence (15, 4, 13), Margaux (12, 13, 17), Xavier (4, 12, 10) et Elisa (16, 5, 9).
Voir le corrigé
data notes ;
    input nom $ int1 int2 int3 ;
    cards ;
Eric 12 3 8
Maxence 15 4 13
Margaux 12 13 17
Xavier 4 12 10
Elisa 16 5 9
;
run ;
Q2 — Ajouter trois colonnes Étendue, Moyenne et Std représentant l'étendue, la moyenne et l'écart-type des notes de chaque étudiant.
Voir le corrigé
data notes2 ;
    set notes ;
    format etendue 4.2  moyenne 4.2  std 4.2 ;
    etendue = max(of int1-int3) - min(of int1-int3) ;
    moyenne = mean(of int1-int3) ;
    std     = std(of int1-int3) ;
run ;
Q3 — Afficher la table avec la PROC PRINT.
Voir le corrigé
proc print data=notes2 ; run ;
Q4 — Trier la table par ordre alphabétique, puis par moyenne décroissante.
Voir le corrigé
proc sort data=notes2 out=notes_tri1 ;
    by nom ;
run ;

proc sort data=notes2 out=notes_tri2 ;
    by descending moyenne ;
run ;
Q5 — Afficher le nom des étudiants et le résultat de la deuxième interrogation, du meilleur au moins bon.
Voir le corrigé
proc sort data=notes2 out=notes_tri3 ;
    by descending int2 ;
run ;

proc print data=notes_tri3 ;
    var int2 ;
    id nom ;
run ;

Point de vigilance : après un tri vers une table de sortie (out=), pensez à diriger la PROC PRINT vers cette nouvelle table triée, et non vers la table d'origine — c'est l'erreur la plus fréquente sur ce type de question.

Exercice 5 (facultatif) — Graphique combiné

On retravaille sur la table temp3 de l'exercice 2.

Tracer sur un même graphique les températures et les précipitations, avec le titre « Précipitations et températures au Canada ». Le graphe des précipitations sera en trait noir sans marque ; celui des températures en pointillé rouge avec une marque en étoile.
Voir le corrigé
symbol1 i=join v=none c=black ;
symbol2 v=star c=red l=2 ;

proc gplot data=temp3 ;
    plot precp*date=1 temp*date=2 / overlay ;
    title "Precipitations et temperatures au Canada" ;
run ;
title ;

Exercice 6 — Courses de voitures (NASCAR)

On s'intéresse aux gains des pilotes lors des courses NASCAR, à partir du fichier nascar.txt (description dans nascar-short-desc.txt).

Q1 — Importer le fichier dans une table SAS nascar.
Voir le corrigé
data nascar ;
    infile "/chemin/nascar.txt" lrecl=100 pad ;
    input Series 1-3  Year 6-9  @12 Race_Year 2.  @16 Finish_Pos 2.  @20 Start_Pos 2.
          @24 Laps 3.  @29 Winnings 7.  @38 Cars 2.  @42 Car_Make $9.  @53 Driver $30. ;
run ;

proc contents data=nascar ; run ;
Q2 — Calculer le montant des gains par année et par pilote, dans une table temporaire gain_annuel.
Voir le corrigé
proc means data=nascar noprint ;
    by year ;
    class driver ;
    var winnings ;
    output out=gain_annuel sum=gain ;
run ;

data gain_annuel2 ;
    set gain_annuel ;
    if _type_ = 0 then delete ;
    drop _type_ ;
run ;
Q3 — En utilisant uniquement l'étape DATA, construire une table all_laps ne contenant que les pilotes ayant fini la course. Combien sont-ils ?
Voir le corrigé
proc sort data=nascar out=nascar_tri ;
    by year descending laps ;
run ;

data all_laps ;
    set nascar_tri ;
    by year ;
    retain laps_max ;
    if first.year then laps_max = laps ;   /* le pilote de tete du classement a boucle le plus de tours */
    if laps = laps_max then output ;       /* on ne garde que ceux qui ont boucle autant de tours que lui */
run ;

proc print data=all_laps (obs=10) noobs ; run ;

Un pilote qui abandonne en course boucle moins de tours que celui qui mène la course jusqu'au bout : comparer le nombre de tours de chaque pilote à celui du meneur de son année est donc un bon indicateur de qui a réellement terminé la course. La sélection elle-même reste une pure étape DATA, construite avec RETAIN et FIRST., exactement comme au module V ; seul le tri préalable (nécessaire à l'instruction BY) passe par une PROC SORT.

Exercice 7 — Factures d'électricité

On s'intéresse au montant (en dollars) des factures d'électricité d'une famille américaine, à partir du fichier electricbill.txt (description dans electricbill-short-desc.txt).

Q1 — Importer le fichier dans une table temporaire electric.
Voir le corrigé
data electric ;
    infile "/chemin/electricbill.txt" ;
    input NUM 1-3  YEAR 5-8  MONTH $ 10-12  BILL 14-19  TEMP 21-24  HDD 26-29  CDD 31-33
          SIZE 35  METER 37  PUMP1 39  PUMP2 41  RIDER_TOTAL 43-52  CONSUMPTION 54-58 ;
run ;

proc contents data=electric ; run ;
Q2 — Les températures sont en degrés F : transformer en degrés C (formule : C = (5/9)*(F-32)).
Voir le corrigé
data electric2 ;
    set electric ;
    format temp_c 4.1 ;
    temp_c = (5/9)*(temp-32) ;
    drop temp ;
run ;
Q3 — Créer une variable date ident identifiant chaque observation à partir de Year et Month.
Voir le corrigé
data electric3 ;
    set electric2 ;
    a = mod(num,12) ;   /* reconstruit un cycle 1 a 12 a partir du numero sequentiel */
    if a = 0 then a = 12 ;
    ident = mdy(a, 1, year) ;
    format ident monyy7. ;
    drop a ;
run ;
Q4 — Représenter graphiquement la série des factures. Que remarquez-vous ? Corriger l'erreur de saisie et refaire le graphique.
Voir le corrigé
symbol1 i=join v=none c=black ;
proc gplot data=electric3 ;
    plot bill*ident=1 / skipmiss ;
run ;

Un point clairement aberrant apparaît fin décembre. En y regardant de plus près (observation NUM=24) : il s'agit d'une véritable erreur de saisie, l'année ayant été notée 93 au lieu de 92.
data electric4 ;
    set electric3 ;
    if num = 24 then year = 1992 ;
    a = mod(num,12) ;
    if a = 0 then a = 12 ;
    ident = mdy(a, 1, year) ;
    format ident monyy7. ;
    drop a ;
run ;

proc gplot data=electric4 ;
    plot bill*ident=1 / skipmiss ;
run ;
Q5 — Calculer et afficher les moyennes annuelles et mensuelles des factures.
Voir le corrigé
proc means data=electric4 ;
    var bill ;
    class year ;
run ;

proc means data=electric4 ;
    var bill ;
    class month ;
run ;
Q6 — Calculer et afficher les moyennes des factures selon le nombre de personnes dans le foyer.
Voir le corrigé
proc means data=electric4 ;
    var bill ;
    class size ;
run ;
Q7 — Calculer et afficher les moyennes des factures avant et après l'installation du nouveau compteur.
Voir le corrigé
proc means data=electric4 ;
    var bill ;
    class meter ;
run ;
Last modified: Friday, 11 September 2026, 2:42 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