News Artikel Foren Projekte Links Über Redscope Join List Random Previous Next Startseite Foren Allgemeine Fragen zu SAS Macro erzeugt Dateifilter 9 June, 2010-11:35 SAS-Fidi Ein Macro bearbeitet die Datei Basis und gibt den Namen einer Variablen Var1 mit den Ausprägungen 0 und 1 aus. Jetzt soll das gleiche Macro für Var1=0 erneut laufen. Daraufhin gibt es Var2 mit den Ausprägungen 0 und 1 aus und soll dann für Var1=0 und Var2=0 erneut laufen usw. In der Datei basis soll also ein Filter gesetzt werden, der abhängig von Ausgabe des Macros ist. Ich kriegs nicht hin und wäre froh über Hilfe. Vilen Dank im Vorraus! VG SAS-Fidi Foren: Allgemeine Fragen zu SAS Hallo SAS-Fidi, ich hätte Hallo SAS-Fidi, 10 June, 2010-10:47 JanHeuer ich hätte hier ein sinnleeres, aber laufendes, Beispiel. Es werden auf eine Variable solange Zufallswerte aufaddiert, bis alle Ausprägungen der Variable ungerade sind. Die Variablen werden vorher auf ganze Zahlen gerundet.
/* Basis wird solange durchgenudelt bis die Summe aller Filtervariablen, die vorher definiert wurden ungleich 0 ist oder die maximale Rundenzahl erreicht ist benutzt Variable Var zur Berechnung */ %MACRO Filter(Basis,Out,Prefix, Var, max=0); %LOCAL ENDE I; %LET I = 0; %LET ENDE = 0; data &Out; set &BASIS.; %DO %WHILE (NOT &ENDE. ); %LET I = %EVAL(&I. + 1); %PUT ROUND &I.; data &OUT.; drop zaehler; set &OUT. end = Ende; %IF &I. > 1 %THEN %DO; if sum(of &PREFIX.1- &PREFIX.%EVAL(&I. - 1)) = 0 then do; &VAR. = &VAR. + floor(ranuni(0) * 5); %END; %ELSE %DO; &VAR. = round(&var., 1); %END; &PREFIX.&I. = %Berech(&VAR.); IF &PREFIX.&I. = 0 then Zaehler + 1; %IF &I. > 1 %THEN %DO; end; %END; if Ende and (Zaehler = 0) then call symput ("Ende","1"); %IF &MAX. > 0 AND &ENDE. = 0 %THEN %LET ENDE = %EVAL(&I. GE &MAX.); %END; %MEND Filter; /* Macro zur Berechnung eines 0/1 Wertes*/ %MACRO Berech(Var1); mod(&var1., 2) %MEND Berech; options nomprint nomlogic nonotes; %Filter(Sashelp.Class, Class, Filter,weight, max=10); options Notes; Schöne Grüße Jan Hm, ich hab hier ein Hm, 15 June, 2010-11:46 SAS-Fidi ich hab hier ein Beispiel, das zwar wiedermal nicht schön ist, aber zeigt, was ich meine:
data test; a=1; b=0; %macro versuch(datei); %let filter=if B=0 then c=3; data malsehen; set &datei; &filter; %mend; %versuch(test); proc print; Das Programm, das ich hier habe, ist zwar komplizierter, aber es soll letztlich das gleiche tun. Die Variable filter wird dort so definiert: %let drüber=%sysfunc(round((&i./2),1)); %let dot_1=node&eb.&drüber; %if %sysfunc(mod(&drüber.,2)=1) %then %let filter=%sysfunc(&filter &dot_1 =1);/*wenn ungerade*/ %if %sysfunc(mod(&drüber.,2)=1) %then %let filter=%sysfunc(&filter &dot_1 =2);/*wenn gerade*/ (wobei &eb und &i Zählvariablen in den übergeordneten Schleifen sind.) Wenn ich dann weiter unten auf &filter zugreifen will, ist diese Variable nicht definiert. Warum? VG SAS-Fidi Lokal und Global 15 June, 2010-12:20 HansKneilmann Hallo, könnte das Problem mit global bzw. lokal zusammenhängen? Wenn die Macro-Variable filter irgendwo oben definiert wurde... könnte das irgendwo auch ein anderer Macro sein??? Dann muß die Macro-Variable filter als globale Macro-Variable definiert sein! Dazu gibt es mehrere Möglichkeiten. Eine ist, die Macro-Variable filter ausserhalb einer Macro-Definition zu definieren bzw. zu initialisieren. Die andere Möglichkeit ist, sie mit %global filter; global zu machen. In diesem Fall darf sie aber nicht zuvor lokal gemacht worden sein... Für genauere Tipps fehlt (mir) eine komplettes vollständiges Beispiel! Gruß Hans Kneilmann, Schäfer Shop GmbH (SSI)
Die Variable Filter wird in Die Variable Filter wird in der gleichen Schleife als global definiert. 15 June, 2010-12:40 SAS-Fidi Ein vollständiges Beispiel ist da schwierig, denn es ist noch in der Mache und ohne Zusammenhang schwierig ztu verstehen. So sieht es bisher aus: %macro ebene(datei,varlist1=,ebene=,maxziel=); %let string00=; %let anzdot=%eval(&ebene**2); %let eb_1=%eval(&ebene-1); %do i=1 %to &anzdot; %do eb=&eb_1 %to 1 %by -1; %global filter; %let filter =; %let drüber=%sysfunc(round((&i./2),1)); %global dot_1; %let dot_1=node&eb.&drüber; %if %sysfunc(mod(&drüber.,2)=1) %then %let filter=%sysfunc(&fi %if %sysfunc(mod(&drüber.,2)=1) %then %let filter=%sysfunc(&fi %let liste=&varlist1; %local pattern; %local regtext; %Let raus=%str(s/ string&eb_1.&dot_1. / /); %let Pattern = %sysfunc(prxparse(&raus.)); %IF &Pattern. NE. %THEN %DO; %sysfunc(prxchange(&pattern.,1,%s data start; set basis; /*&filter;*/ /*<********************************************** %einzel(baum,drpscale2,varlist1=&liste,max=&maxziel,ebene=&eben %mend; %ebene(start,varlist1=visuscale hba1c ydiab typdiab hypscale fett nikotin bmiscale durchblut herzinf apoplex mpathie moed Wie gesagt, ist es noch sehr unfertig. VG SAS-Fidi &Filter wird niemals definiert Hallo SAS-Fidi, 15 June, 2010-16:10 JanHeuer in deinem Beispiel wird Filter niemals definiert, für Ebene < 2. In deinem Macro wird die globale Variable Filter in der inneren Schleife definiert. Du rufst das Macro mit dem Wert Ebene = 1 auf. Dies führt in der inneren Schleife zu dem Ausdruck %DO EB = 0 %TO 1 %BY -1; Dies führt dazu, dass die innere Schleife niemals ausgeführt wird, also wird auch keine
globale Variable Filter definiert. %macro ebene(datei,varlist1=,ebene=,maxziel=); %let anzdot=%eval(&ebene.**2); %let eb_1=%eval(&ebene.-1); %do i=1 %to &anzdot; %do eb=&eb_1 %to 1 %by -1; %PUT Hier gelangt das Macro nie hin, für Werte < 2; %mend; Schöne Grüße Jan Hm, das stimmt, das muß noch Hm, das stimmt, das muß noch abgefangen werden. 16 June, 2010-10:07 SAS-Fidi Das ist aber wohl nicht das einzige Problem, denn so sieht das Log für ebene=5 aus:
278 %ebene(baum,varlist1=visuscale hba1c ydiab typdiab hyps 278! alter MLOGIC(EBENE): Beginning execution. 279 nikotin bmiscale durchblut herzinf apoplex mp 279! sysdruck diasdruck,ebene=5,maxziel=2); MLOGIC(EBENE): Parameter DATEI has value baum MLOGIC(EBENE): Parameter VARLIST1 has value visuscale hba1c hypscale fette niere alter nikotin bmiscale apoplex mpathie moedem sysdruck diasdruck MLOGIC(EBENE): Parameter EBENE has value 5 MLOGIC(EBENE): Parameter MAXZIEL has value 2 MLOGIC(EBENE): %LET (variable name is STRING00) MLOGIC(EBENE): %LET (variable name is ANZDOT) MLOGIC(EBENE): %LET (variable name is EB_1) MLOGIC(EBENE): %DO loop beginning; index variable I; start stop value is 25; by value is 1. MLOGIC(EBENE): %DO loop beginning; index variable EB; start stop value is 1; by value is -1. MLOGIC(EBENE): %GLOBAL FILTER MLOGIC(EBENE): %LET (variable name is FILTER) MLOGIC(EBENE): %LET (variable name is DRÜBER) MLOGIC(EBENE): %GLOBAL DOT_1 MLOGIC(EBENE): %LET (variable name is DOT_1) ERROR: Expected close parenthesis after macro function invoc ERROR: Required operator not found in expression: %sysfunc(m ERROR: The macro CARTEBENE will stop executing. MLOGIC(EBENE): Ending execution. 280 281 proc print data=aufheb noobs; ERROR: File WORK.AUFHEB.DATA does not exist. 282 NOTE: The SAS System stopped processing this step because of NOTE: PROCEDURE PRINT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds VG SAS-Fidi Klammersetzung Hallo SAS-Fidi, 16 June, 2010-10:38 JanHeuer vermutlich kommt die Fehlermeldung aus folgender Zeile: %if %sysfunc(mod(&drüber.,2)=1) %then... /* Syntaxfehle %if %sysfunc(mod(&drüber.,2))=1 %then... /* korrekte Sy Schöne Grüße Jan
Fast, aber noch nicht ganz! Oh, danke! Manchmal ist man echt betriebsblind! Jetzt sieht es so aus: 16 June, 2010-12:26 SAS-Fidi %macro ebene(datei,varlist1=,ebene=,maxziel=); /*Startebene ist Ebene 0!!!*/ %global filter; %let string00=; %let anzdot=%eval(2**&ebene); /*hier war %let eb_1=%eval(&ebene-1); %do i=1 %to &anzdot; %if &ebene>=2 %then %do eb=&eb_1 %to 1 %by -1; %if &ebene=0 %then %let &filter=; %let drüber=%sysfunc(round((&i./2),1 %global dot_1; %let dot_1=node&eb.&drüber; %if %sysfunc(mod(&drüber.,2))=1 %the %if %sysfunc(mod(&drüber.,2))=0 %the %let liste=&varlist1; %local pattern; %local regtext; %Let raus=%str(s/ string&eb_1.&dot_1. / /); %let Pattern = %sysfunc(prxparse(&raus.)); %IF &Pattern. NE. %THEN %DO; %sysfunc(prxchange(&pat data baum; set basis; &filter; /*<**************************************** %cut(baum,drpscale2,varlist1=&liste,max=&maxziel,eben %if (&ebene=1 and &i=1) %then %let filter=%sysfunc(&n %if (&ebene=1 and &i=2) %then %let filter=%sysfunc(&n %mend; %ebene(baum,varlist1=visuscale hba1c ydiab typdiab hyps nikotin bmiscale durchblut herzinf apoplex mpath proc print data=aufheb noobs; Die Variablen node&ebene&cut werden im Macro cut jeweils als global angelegt: data merken; set merken; if _n_=1; ebene=&ebene; %global node&ebene.&cut.; /*rename node&ebene.&cut.=node;*/
Das Log sieht so aus: MLOGIC(EBENE): Beginning execution. 896 nikotin bmiscale durchblut herzinf apopl 896! sysdruck diasdruck,ebene=1,maxziel=2); MLOGIC(EBENE): Parameter DATEI has value baum MLOGIC(EBENE): Parameter VARLIST1 has value visuscale hypscale fette niere alter nikotin bmis apoplex mpathie moedem sysdruck diasdruck MLOGIC(EBENE): Parameter EBENE has value 1 MLOGIC(EBENE): Parameter MAXZIEL has value 2 MLOGIC(EBENE): %GLOBAL FILTER MLOGIC(EBENE): %LET (variable name is STRING00) MLOGIC(EBENE): %LET (variable name is ANZDOT) MLOGIC(EBENE): %LET (variable name is EB_1) MLOGIC(EBENE): %DO loop beginning; index variable I; s stop value is 2; by value is 1. MLOGIC(EBENE): %IF condition &ebene>=2 is FALSE MLOGIC(EBENE): %LET (variable name is LISTE) MLOGIC(EBENE): %LOCAL PATTERN MLOGIC(EBENE): %LOCAL REGTEXT MLOGIC(EBENE): %LET (variable name is RAUS) MLOGIC(EBENE): %LET (variable name is PATTERN) MLOGIC(EBENE): %IF condition &Pattern. NE. is TRUE MPRINT(EBENE): visuscale hba1c ydiab typdiab hypscale nikotin bmiscale durchblut herzinf apoplex mpathie moed NOTE: Line generated by the macro function "SYSFUNC". 1 visuscale hba1c ydiab typdiab hypscale fette nie --------- 180 1! nikotin bmiscale durchblut herzinf apoplex mpathie 1! diasdruck MPRINT(EBENE): data baum; MPRINT(EBENE): set basis; NOTE: Line generated by the macro variable "FILTER". 1 &node11 =1 -- 180 MPRINT(EBENE): =1; MPRINT(EBENE): ERROR 180-322: Statement is not valid or it is used out NOTE: The SAS System stopped processing this step becau WARNING: The data set WORK.BAUM may be incomplete. Whe there were 0 observations and 24 variables. WARNING: Data set WORK.BAUM was not replaced because th NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.01 seconds Es wird also laaaaaaangsam besser, oder? VG SAS-Fidi
Verkettungsoperator? Hallo SAS-Fidi, 16 June, 2010-13:02 JanHeuer wahrscheinlich ist hier noch ein Fehler, da Texte in Macros nicht mit dem Verkettungsoperator verkettet werden: %let filter=%sysfunc(&filter &dot_1 =2); /* wahrscheinlich gemeint */ %let filter=&filter.&dot_1. = 2; Dies kommt in mehreren Varianten im Text vor. Außerdem gibt es immer noch Code in der inneren Schleife, der nie erreicht wird. /* wird niemals ausgeführt, da die Bedingung für d %IF &Ebene. >= 2 %THEN %DO...; %if &ebene=0 %then %let &filter=;...; %END; Schöne Grüße Jan Uh, das kommt davon, wenn man 21 June, 2010-13:21 SAS-Fidi Uh, das kommt davon, wenn man aus einem anderen Programm Zeilen klaut. Jetzt sieht es so aus:
%macro ebene(datei,varlist1=,ebene=,maxziel=); /*Startebene ist Ebene 0!!!*/ %global filter; %let string00=; %let anzdot=%eval(2**&ebene); %let eb_1=%eval(&ebene-1); %do i=1 %to &anzdot; %if &ebene>=2 %then %do eb=&eb_1 %to 1 %by -1; %if &ebene=0 %then %let &filter %let drüber=%sysfunc(round((&i. %let dot_1=&node&eb.&drüber; %global dot_1; %if %sysfunc(mod(&drüber.,2))=1 %if %sysfunc(mod(&drüber.,2))=0 %if &ebene=0 %then %let dot_1=; %if &ebene=1 %then %let dot_1=&node01; %let liste=&varlist1; %local pattern; %local regtext; %Let raus=%str(s/ string&eb_1.&dot_1. / /); %let Pattern = %sysfunc(prxparse(&raus.)); %IF &Pattern. NE. %THEN %DO; %sysfunc(prxchange %if ebene=0 %then %let filter=; %if (&ebene=1 and &i=1) %then %let filter=if &no %if (&ebene=1 and &i=2) %then %let filter=if &no data baum; set basis; &filter; %cut(baum,drpscale2,varlist1=&liste,max=&maxziel %mend; Leider läuft es immer noch nicht. Das liegt wohl in erster Linie daran, daß aus den Macro Cut für die node-variablen Leerstrings kommen. Das Problem dort ist, daß in einem Data-Step eine Variable node&ebene.&cut. berechnet wird. Diese Variable soll dann nach der Berechnung als global definiert werden, damit ich sie in Ebene verwenden kann. Leider funbktioniert das nicht. Gruß SAS-Fidi Mein jetziger falscher Code 21 June, 2010-13:48 SAS-Fidi Mein jetziger falscher Code (Auszug aus dem Macro!):
... data merken; set merken; if _n_=1; ebene=&ebene; %global node&ebene.&cut.; %let node&ebene.&cut=%sysget(node&ebene.&cut)... In der Datei merken gibt es eine Variable node&ebene.&cut. Diese Variable soll nach Abschluß des Macros auch andseren Macros zur Verfügung stehen. Gruß SAS-Fidi call symput Hallo SAS-Fidi, 21 June, 2010-14:42 JanHeuer die globale Variable sollte bereits vorher definiert sein. Die Zuweisung zu einer Macrovariablen erfolgt mit symput. Die Ansprache der neuen Macrovariablen erfolgt mit doppeltem &&. %GLOBAL node&ebene.&cut.;... /* Wertzuweisung */ Data _NULL_; set merken(obs=1); call symput("node&ebene.&cut.",put(node&ebe... /* Wertausgabe */ %put &&node&ebene.&cut.;... Schöne Grüße Jan Grummel jetzt läuft soweit 23 June, 2010-10:59 SAS-Fidi
Grummel jetzt läuft soweit alles, aber ausgerechnet &filter wird nicht richtig erzeugt. Ebene 0 (hier ist alles noch ok!): MPRINT(EBENE): data baum; MPRINT(EBENE): set basis; MPRINT(EBENE): ; MPRINT(EBENE): Ebene 1 (auch noch alles ok!): MPRINT(EBENE): data baum; MPRINT(EBENE): set basis; MPRINT(EBENE): if mpathie =1; MPRINT(EBENE): Ebene 2 (hier geht gar nichts mehr!): MPRINT(EBENE): data baum; MPRINT(EBENE): set basis; NOTE: Line generated by the macro variable 1 if mpathie =1ydiab =1 ----- 22 MPRINT(EBENE): if mpathie =1ydiab =1 ; MPRINT(EBENE): ERROR 180-322: Statement is not valid or i ERROR 22-322: Syntax error, expecting one -, /, ;, <, <=, <>, =, >, >< MAX, MIN, NE, NG, NL, NOTIN, NOTE: The SAS System stopped processing th WARNING: The data set WORK.BAUM may be inc there were 0 observations and 24 WARNING: Data set WORK.BAUM was not replac NOTE: DATA statement used (Total process t real time 0.00 seconds cpu time 0.00 seconds Es fehlt das and in der Variablen &filter. Eigentlich sollte die Variable so aussehen: if mpathie =1 and ydiab =1 ; Das Macro ebene sieht aktuell so aus:
%macro cartebene(datei,varlist1=,ebene=,ma /*Startebene ist Ebene 0!!!*/ %global filter; %let string00=; %let anzdot=%eval(2**&ebene); %let eb_1=%eval(&ebene-1); %do i=1 %to &anzdot; %if &ebene>=2 %then %do eb=&eb_1 %to 1 %by - %if &ebene=0 %then %let %let drüber=%sysfunc(ro %let dot_1=&node&eb.&dr %global dot_1; %if %sysfunc(mod(&drübe %if %sysfunc(mod(&drübe %if &ebene=0 %then %let dot_1=; %if &ebene=1 %then %let dot_1=&node01; %let liste=&varlist1; %local pattern; %local regtext; %Let raus=%str(s/ string&eb_1.&dot_1. / %let Pattern = %sysfunc(prxparse(&raus.) %IF &Pattern. NE. %THEN %DO; %sysfunc(p %if ebene=0 %then %let filter=; %if (&ebene=1 and &i=1) %then %let filte %if (&ebene=1 and &i=2) %then %let filte data baum; set basis; &&filter; %cart1cut(baum,drpscale2,varlist1=&liste %mend; %cartebene(baum,varlist1=visuscale hba1c y nikotin bmiscale durchblut herzi %cartebene(baum,varlist1=visuscale hba1c y nikotin bmiscale durchblut herzi %cartebene(baum,varlist1=visuscale hba1c y nikotin bmiscale durchblut herzi VG SAS-Fidi AND auch an Filter zuweisen Hallo SAS-Fidi, 23 June, 2010-11:21 JanHeuer
der Fehler steckt m. E. in der Filterzuweisung. %if %sysfunc(mod(&drüber.,2))=1 %then % /* statt */ %if %sysfunc(mod(&drüber.,2))=1 %then % Schöne Grüße Jan So, endlich bin ich dazu 20 July, 2010-13:58 SAS-Fidi So, endlich bin ich dazu gekommen am Macro weiter zu arbeiten! So sieht es jetzt aus:
%macro ebene(datei,varlist1=,ebene=,m /*Startebene ist Ebene 0!!!*/ %global stop; %let stop=0; %if &ebene=0 %then %do; %global filt %let string00=; %let eb_1=%eval(&ebene-1); %let anzdot=%eval(2**&ebene); %do z=1 %to &anzdot; %if &ebene>=2 %then %do eb=&ebene %to 1 %let anz_1=%eval(2**&eb_1); %global drueber; %let drueber=%sysf /*%global dot_1;*/ %if &&node&eb_1.&d %if &&filter&eb_1.&drueber. eq %if &ebene=0 %then %let dot_1=; %if &ebene=1 %then %let dot_1=&node %let liste=&varlist1; %local pattern; %local regtext; %Let raus=%str(s/ string&eb_1.&dot_ %let Pattern = %sysfunc(prxparse(&r %IF &Pattern. NE. %THEN %DO; %sysf %if (&ebene=1 and &z=1) %then %do; %if (&ebene=1 and &z=2) %then %do; %if &stop ne 1 %then %do; data baum; set basis; &&filter&eb %1cut(baum,d %mend; %ebene(baum,varlist1=visuscale hba1c nikotin bmiscale durchblut her Leider macht es immer noch nicht so ganz, was ich möchte. Für Ebene=2 ergibt sich für data baum folgendes: Cut=1: if mpathie =1 and ydiab=1; Cut=2: if mpathie =1 and ydiab=2; Cut=3: if mpathie =1 and ydiab=1; Cut=4: if mpathie =1 and ydiab=2; Es soll aber dort stehen: Cut=1: if mpathie =1 and ydiab=1;
Cut=2: if mpathie =1 and ydiab=2; Cut=3: if mpathie =2 and ydiab=1; Cut=4: if mpathie =2 and ydiab=2; VG SAS-Fidi Sodele, hab das Problem 21 July, 2010-13:47 SAS-Fidi Sodele, hab das Problem selbst gelöst! Das einzige, was jetzt noch stört, ist folgende Felhermeldung, die allerdings keinerlei Auswirkungen hat:# MLOGIC(EBENE): %GLOBAL FILTER11 MLOGIC(EBENE): %LET (variable name NOTE: Line generated by the macro f 1 visuscale hba1c ydiab typdia --------- 180 1! nikotin bmiscale durchblut her 1! diasdruck MLOGIC(EBENE): %IF condition (&ebe MLOGIC(EBENE): %IF condition &stop MPRINT(EBENE): data baum; MPRINT(EBENE): set basis; MPRINT(EBENE): if mpathie =1; MPRINT(EBENE): ERROR 180-322: Statement is not val Sie taucht in allen Versionen des Macros auf. VG SAS-Fidi