2013-03-22 12 views
6

ich für eine Weile ein Äquivalent des für in Schleife (wie in Python oder R) in SAS 9.3 Makrosprache zu suchen. Die DO loop scheint die Lösung zu sein, hat aber nicht genau so funktioniert, wie ich es möchte. Ich gründete eine Möglichkeit, es in einem Datenschritt mit einer DO-Schleife zu tun, aber es funktioniert nicht mit der Makro-Sprache. Zum Beispiel wird in einem Daten Schritt, dieser Code arbeitet:"Für in" loop äquivalent in SAS 9.3

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

Und dann, als die Log-Prompt erwartet:

1 
3 
5 
9 

Wenn ich versuche, das gleiche mit einem % DO Schleife zu tun In einem Makro habe ich einen Fehler.

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

%test(); 

Das Protokoll promp diese Meldungen:

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

ich in SAS ganz neu bin und so hoffe ich, Stackoverflow meine Frage nicht zu dumm ist. Es ist so einfach, dies in Python und R zu tun, dann muss es eine einfache Möglichkeit haben, dies in SAS zu tun.

Dankten um Hilfe - J. Muller

Antwort

6

Die nächstgelegene ich auf diesem Muster in SAS Makrosprache immer gekommen sind, ist dies:

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

(Achtung: nicht getestet, da ich nicht mehr ein SAS-Installation habe ich das testen kann heraus.)

+0

Ich habe es versucht und es funktioniert perfekt. Es ist nicht so einfach wie Python oder R-Syntax, aber es funktioniert auch gut mit Zeichenliste. Vielen Dank! – jomuller

4

Sie können sicher um es auf diese Weise erhalten:

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(); 

Aber ich denke, man kann in der Regel diese Art von Anruf vermeiden, indem Ihr Makro mehrere Male ausgeführt wird eher als zu versuchen, die Schleife innerhalb des Makros zu steuern. Zum Beispiel vorstellen, einen Datensatz und einen Makro:

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

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

Jetzt Sie anrufen% Test wollen() einmal für jeden Wert in dieser Liste. Okay, einfach zu machen.

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

&testcall; 

, die genauso gut wie Ihre% tun in Schleife arbeitet, außer es Daten angetrieben, was bedeutet, wenn Sie wollen, ändern Sie die Anrufe, die Sie nur den Datensatz ändern (oder wenn die Datenänderungen, wird der Anruf automatisch ändert!) . Im Allgemeinen ist SAS effektiver, wenn es als datengesteuerte Programmierung und nicht als vollständig geschriebener Code entworfen wird.

+0

Ich habe etwas ähnliches für numerische Listen aber – jomuller

+1

Ja, wenn Sie Zeichenlisten tun möchten, müssen Sie die Liste wie in Simons Beispiel scannen. Ich würde bemerken, dass die SAS-Makrosprache nicht genau eine voll ausgestattete Sprache ist - erwarte nicht, dass sie es ist. Die meisten Dinge können innerhalb der Basis-SAS getan werden, ohne ernsthafte Programmierung in der Makrosprache zu machen, darüber hinaus, repetitiven Code zu vermeiden. Beispiel wurde der Antwort hinzugefügt. – Joe

+0

(Ende meines Satzes, sorry technisches Problem) ... es funktioniert nicht für eine Charakterliste, glaube ich. – jomuller