2013-04-23 9 views
5

Wie können Sie einen SAS-Datensatz aus einem anderen Datensatz erstellen, indem Sie nur die letzten n Beobachtungen des ursprünglichen Datensatzes verwenden? Das ist einfach, wenn Sie den Wert von n kennen. Wenn ich nicht weiß, wie kann das gemacht werden?SAS - Wie bekomme ich letzte 'n' Beobachtungen aus einem Datensatz?

+1

Was meinst du, du weißt nicht 'n'? Wie werden Sie den Wert von 'n' herausfinden - ist es eine Datensatzvariable, eine Makrovariable, ein Parameter? – Joe

Antwort

8

Dies setzt voraus, dass Sie eine Makrovariable haben, die angibt, wie viele Beobachtungen Sie möchten. NOBS teilt Ihnen die Anzahl der Beobachtungen im Datensatz mit, ohne das Ganze zu lesen.

%let obswant=5; 
data want; 
set sashelp.class nobs=obscount; 
if _n_ gt (obscount-&obswant.); 
run; 
4

Mit Joes Beispiel einer Makrovariablen die Anzahl der Beobachtungen geben Sie, hier wollen, ist eine andere Antwort:

%let obswant = 10; 
data want; 
    do _i_=nobs-(&obswant-1) to nobs; 
     set have point=_i_ nobs=nobs; 
     output; 
     end; 
    stop; /* Needed to stop data step */ 
run; 

Dies sollte eine bessere Leistung, da sie nur die spezifischen Beobachtungen liest man will.

+0

Ich bin gespannt auf die Bedingungen für "das sollte besser funktionieren". Ich vermute, es ist ein Teil von jedem; Der wahlfreie Zugriff ist nicht so schnell wie der sequenzielle Zugriff, daher gibt es dort einen gewissen Verlust. Kann es ausprobieren, wenn ich etwas Zeit habe. Ich vermute, wenn Sie die meisten Beobachtungen verwenden, ist es schneller, es sequenziell zu tun, aber wenn es ein großer Datensatz ist und Sie eine kleine Anzahl von Beobachtungen wollen, ist es schneller, es zufällig zu tun = Zugang. Wünscht mir, dass SAS eine Möglichkeit hat, einen Datensatz in umgekehrter Reihenfolge zu öffnen, ohne ihn vorher sortieren zu müssen. – Joe

+3

@Joe Stelle dir einen Datensatz mit 1 Million Obs vor und du willst den "letzten" 10. Mit dieser Technik werden nur 10 "Eingabe" -Operationen durchgeführt. Die Verwendung nur des NOBS-Werts erfordert 1 Million "Eingabe" -Operationen. Abhängig davon, wie breit der Datensatz ist, kann dieser Unterschied sehr signifikant sein. – BellevueBob

+1

Richtig, ich sehe sicherlich die Möglichkeit, dass es schneller geht. Ich bin neugierig, an welchem ​​Punkt es schneller/langsamer ist (dh, welche Größe des Datasets, was% der Daten gezogen wird - 10 von 1MM natürlich wäre schneller, aber was ist 500k von 1MM?) – Joe

1

Aus Gründen der Vielfalt, hier ist ein anderer Ansatz (nicht unbedingt ein besserer)

%let obswant=5; 

proc sql noprint; 
select nlobs-&obswant.+1 into :obscalc 
from dictionary.tables 
where libname='SASHELP' and upcase(memname)='CLASS'; 
quit; 

data want; 
set sashelp.class (firstobs=&obscalc.); 
run; 
+1

Hinweis: Sie möchten angeben Format bei Verwendung von select..into, ansonsten wird der Wert als BEST8. formatiert, was zu seltsamen Fehlern führt, wenn Sie einen Wert> = 100.000.000 wählen (er ist in Exponentialschreibweise formatiert, was zum Runden führt). – Nickolay

2

Wenn der Datensatz groß ist, könnten Sie nicht den gesamten Datensatz lesen mögen. Stattdessen könnten Sie eine Konstruktion versuchen, die zuerst die Gesamtzahl der Beobachtungen im Datensatz liest. Also, wenn Sie die letzten Beobachtungen haben möchten:

data t; 
    input x; 
datalines; 
1 
2 
3 
4 
; 

%let dsid=%sysfunc(open(t)); 
%let num=%sysfunc(attrn(&dsid,nlobs)); 
%let rc=%sysfunc(close(&dsid)); 
%let number = 2; 

data tt; 
set t (firstobs = %eval(&num.-&number.+1)); 
run; 
Verwandte Themen