2013-04-23 17 views
5

Come è possibile creare un dataset SAS da un altro set di dati utilizzando solo le ultime n osservazioni dal set di dati originale. Questo è facile quando conosci il valore di n. Se non so 'n' come si può fare?SAS - Come ottenere le ultime osservazioni di 'n' da un set di dati?

+1

Cosa intendi per non sapere "n"? Come scoprirai il valore di 'n' - è una variabile del set di dati, una variabile macro, un parametro? – Joe

risposta

8

Si presume che si disponga di una variabile macro che indica quante osservazioni si desidera. NOBS indica il numero di osservazioni nel set di dati attualmente senza leggere il tutto.

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

Utilizzando l'esempio di Joe di una variabile macro per specificare il numero di osservazioni che vuoi, qui è un'altra risposta:

%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; 

Questo dovrebbe funzionare meglio dal momento che legge solo le osservazioni specifiche che si desidera.

+0

Sono curioso delle condizioni per "questo dovrebbe funzionare meglio". Sospetto che siano alcuni di ciascuno; l'accesso casuale non è veloce come l'accesso sequenziale, quindi c'è una perdita lì. Posso testarlo se ho un po 'di tempo. Sospetto che se stai usando la maggior parte delle osservazioni sarà più veloce farlo in modo sequenziale, ma se si tratta di un set di dati di grandi dimensioni e desideri un numero ridotto di osservazioni è più veloce farlo random = access. Mi fa piacere che SAS abbia un modo per aprire un set di dati in ordine inverso senza doverlo prima ordinare. – Joe

+3

@Joe Immagina un set di dati con 1 milione di obs e vuoi l'ultimo. 10. Usando questa tecnica, vengono eseguite solo 10 operazioni di "input". L'uso del solo valore NOBS richiede 1 milione di operazioni di "input". A seconda di quanto "ampio" è il set di dati, questa differenza può essere molto significativa. – BellevueBob

+1

Giusto, vedo certamente la possibilità che questo sia più veloce. Sono curioso di sapere a che punto è più veloce/più lento (ovvero, quale dimensione del set di dati, quale percentuale di dati viene tirata - 10 da 1 MM ovviamente sarebbe più veloce, ma che dire di 500k da 1MM?) – Joe

1

Per motivi di varietà, ecco un altro approccio (non necessariamente uno migliore)

%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

Nota: si desidera specificare formato quando si usa select..into, altrimenti il ​​valore è formattato come BEST8., che porta a strani bug quando si seleziona un valore> = 100.000.000 (è formattato in notazione esponenziale, che porta all'arrotondamento). – Nickolay

2

Se il set di dati è grande, non si potrebbe desiderare di leggere l'intero set di dati. Invece potresti provare una costruzione che legge il numero totale di osservazioni nel set di dati prima. Quindi se vuoi avere l'ultima osservazione:

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; 
Problemi correlati