2013-03-22 5 views
6

sto cercando per un po 'l'equivalente del per in ciclo (come in Python o in R) nel SAS 9.3 macro lingua. Il DO loop sembra essere la soluzione ma non ha funzionato esattamente come voglio. Ho trovato un modo per farlo in una fase di dati con un ciclo DO ma non funziona con il linguaggio macro. Per esempio, in un passaggio di dati, questo codice sta lavorando:"Perché in" ciclo equivalente in SAS 9.3

DATA _NULL_; 
    DO i = 1,3,5,9; 
    PUT i; 
    END; 
RUN; 

E poi il prompt di registro come previsto:

1 
3 
5 
9 

Quando provo a fare lo stesso con un % DO ciclo in una macro, ho un errore.

%MACRO test(); 
    %DO i = 1,2,4,9 ; 
    %PUT i = &i; 
    %END; 
%MEND; 

%test(); 

Il registro promp questi messaggi:

ERROR: Expected %TO not found in %DO statement. 
ERROR: A dummy macro will be compiled 

Sono abbastanza nuovo a SAS e StackOverflow quindi spero che la mia domanda non è troppo stupido. È così semplice farlo in Python e R quindi deve avere un modo semplice per farlo in SAS.

di Grazie per un aiuto - J. Muller

risposta

6

Il più vicino che abbia mai incontrato in questo modello in SAS linguaggio macro è questo:

%MACRO test(); 

%let j=1; 
%let vals=1 2 4 9; 
%do %while(%scan(&vals,&j) ne); 
    %let i=%scan(&vals, &j); 

    %put &i; 

    %let j=%eval(&j+1); 
%end; 
%MEND; 

%test(); 

(Attenzione: non testato, in quanto non ho più un impianto di SAS posso testare il tutto su.)

+0

L'ho provato e funziona perfettamente. Non è semplice come la sintassi Python o R, ma funziona bene anche con la lista dei caratteri. Grazie! – jomuller

4

È certamente possibile aggirare in questo modo:

options mindelimiter=,; 
options minoperator; 
%MACRO test(); 
    %DO i = 1 %to 9 ; 
    %if &i in (1,2,4,9) %then %do; 
    %PUT i = &i; 
    %END; 
    %end; 
%MEND; 

%test(); 

Tuttavia, penso che di solito è possibile evitare questo tipo di chiamata eseguendo la macro più volte piuttosto di tentare di controllare il loop all'interno della macro. Per esempio, immaginate un insieme di dati e una macro:

data have; 
input x; 
datalines; 
1 
2 
4 
9 
;;;; 
run; 

%macro test(x); 
%put &x; 
%mend test; 

Ora che si desidera chiamare prova%() una volta per ogni valore in tale elenco. Ok, facile da fare.

proc sql; 
select cats('%test(',x,')') into :testcall separated by ' ' from have; 
quit; 

&testcall; 

che funziona così come il vostro% fare in loop, tranne che è basati su dati, vale a dire se si desidera modificare le chiamate basta cambiare il set di dati (o se le modifiche dei dati, la chiamata passa automaticamente!) . In generale, SAS è più efficace se progettato come programmazione basata sui dati piuttosto che come codice interamente scritto.

+0

Ho usato qualcosa di simile per gli elenchi numerici ma – jomuller

+1

Sì, se si desidera fare elenchi di caratteri è necessario eseguire la scansione dell'elenco come nell'esempio di Simon. Vorrei notare che il linguaggio macro SAS non è esattamente un linguaggio completo - non aspettatevi che lo sia. La maggior parte delle cose possono essere fatte all'interno di SAS di base, senza fare serie programmazioni nel linguaggio macro oltre ad evitare codice ripetitivo. Esempio aggiunto alla risposta. – Joe

+0

(fine della mia frase, scusa problema tecnico) ... non funziona per una lista di caratteri, credo. – jomuller