Lors de l'exploration de données ou du débogage, il est fréquent de vouloir isoler uniquement la "fin" d'une table (dataset). Contrairement à l'option OBS=10 qui nous donne le début, récupérer les 10 dernières observations d'une table contenant $N$ lignes demande une approche plus réfléchie, surtout si la table est volumineuse.
Note : L'approche naïve (Tri Décroissant)
La première idée qui vient souvent à l'esprit est de trier la table par ordre chronologique inverse et de prendre les premières lignes.
proc sort data=MA_TABLE out=sorted_table;
by descending date_variable;
run;
data last_ten;
set sorted_table (obs=10);
run;
1
PROC SORTDATA=MA_TABLE out=sorted_table;
2
BY descending date_variable;
3
RUN;
4
5
DATA last_ten;
6
SET sorted_table (obs=10);
7
RUN;
Verdict : À éviter sur les grosses tables.
Pourquoi ? Trier une table de millions de lignes consomme énormément de ressources CPU et I/O simplement pour lire 10 lignes. C'est inefficace.
Note : L'approche arithmétique (NOBS et IF)
Une méthode beaucoup plus propre consiste à utiliser l'option NOBS dans l'instruction SET. Cette option stocke le nombre total d'observations dans une variable temporaire lors de la compilation, sans avoir à lire la table.
data last_ten;
set MA_TABLE nobs=total_obs;
/* On ne garde que si le numéro de ligne (_N_) est dans les 10 derniers */
if _N_ > (total_obs - 10);
run;
1
DATA last_ten;
2
SET MA_TABLE nobs=total_obs;
3
/* On ne garde que si le numéro de ligne (_N_) est dans les 10 derniers */
Note : L'approche haute performance (Accès Direct avec POINT=)
C'est la solution optimale recommandée par les experts. L'objectif est d'utiliser l'accès aléatoire (Direct Access) pour sauter directement à la fin du fichier sans lire le début.
On combine NOBS (pour connaître la fin) et POINT (pour aller à une ligne précise).
data last_ten;
/* Boucle de la ligne N-9 jusqu'à la ligne N */
do i = (total_obs - 9) to total_obs;
set MA_TABLE nobs=total_obs point=i;
output;
end;
stop; /* IMPORTANT : stop évite une boucle infinie avec l'instruction POINT */
run;
1
DATA last_ten;
2
/* Boucle de la ligne N-9 jusqu'à la ligne N */
3
DO i = (total_obs - 9) to total_obs;
4
SET MA_TABLE nobs=total_obs point=i;
5
OUTPUT;
6
END;
7
stop; /* IMPORTANT : stop évite une boucle infinie avec l'instruction POINT */
Note technique : L'instruction STOP est obligatoire car l'instruction SET avec POINT= ne rencontre jamais de marqueur de fin de fichier (End-of-File).
Note : L'approche Macro (FIRSTOBS dynamique)
Une alternative intéressante consiste à calculer le point de départ dans une étape précédente, puis à utiliser l'option FIRSTOBS.
/* Étape 1 : Calculer le point de départ */
data _null_;
set MA_TABLE nobs=n;
start_point = n - 9;
call symput('start_obs', start_point);
run;
/* Étape 2 : Lire à partir de ce point */
data last_ten;
set MA_TABLE (firstobs=&start_obs);
run;
1
/* Étape 1 : Calculer le point de départ */
2
DATA _null_;
3
SET MA_TABLE nobs=n;
4
start_point = n - 9;
5
call symput('start_obs', start_point);
6
RUN;
7
8
/* Étape 2 : Lire à partir de ce point */
9
DATA last_ten;
10
SET MA_TABLE (firstobs=&start_obs);
11
RUN;
Verdict : Fonctionnel mais verbeux. La méthode 3 reste supérieure car elle tient en une seule étape Data.
Points d'attention et Limitations
Pour conclure, voici quelques nuances techniques soulevées lors de la discussion :
The codes and examples provided on WeAreCAS.eu are for educational purposes. It is imperative not to blindly copy-paste them into your production environments. The best approach is to understand the logic before applying it. We strongly recommend testing these scripts in a test environment (Sandbox/Dev). WeAreCAS accepts no responsibility for any impact or data loss on your systems.
SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration. WeAreCAS is an independent community site and is not affiliated with SAS Institute Inc.
This site uses technical and analytical cookies to improve your experience.
Read more.