LesezeichenAbonnierenRSS-Feed abonnieren
HeideTribius
Fluorite | Level 6

hallo zusammen,

 

ich möchte in einem Makro ein Dataset anlegen und anschließend in Abhängigkeit der Anzahl Datensätze weitere Schritte unternehmen. Es gelingt mir nicht, die Makrovariable, die die Anzahl Datensätze beinhalten soll (anzobs) enthält immer denselben Wert.

Irgendwie scheint der Datastep erst nach Durchlauf des Makros angelegt zu werden? Kann man das irgendwie anders lösen?

 

Ich möchte gern, dass das Programm für alle IDs die Anzahl der selektierten Obs ausweist und für ID 1 und 2 "hallo" ausgibt:

 

dm 'cle log';
data daten;
   input id;
cards;
1
1
2
;
run;

data user;
   input id;
cards;
1
2
3
;
run;

%macro test(id=);

   data datenauszug;
      set daten(where=(id=&id));
   run;

   %let dsid    = %sysfunc(open(datenauszug));
   %let anzobs  = %sysfunc(attrn(&dsid, nlobs));
   %let rc      = %sysfunc(close(&dsid));
   %put &anzobs;

   %if &anzobs > 0 %then %do;
      %put 'hallo';
   %end;
%mend test;

data _null_;
   set user;
   call execute('%test(id='!!id!!')');
run;

 

Hat einer eine Idee?

vielen Dank!

6 ANTWORTEN 6
JMS
Obsidian | Level 7 JMS
Obsidian | Level 7
durch das call execute muss das datenauszug warten, bis data _null_ fertig ist.
Kurt_Bremser
Super User

Das ist das "klassische" Timing-Problem bei der Ausführung von Makros mit call execute. Die Makro-Anweisungen werden gleich an den Makroprozessor übergeben, data und proc steps müssen aber auf das Ende des momentan laufenden steps warten.

Man muss den Makro zusätzlich maskieren:

call execute('%nrstr(%test(id='!!id!!'))');
GrischaPfister
Fluorite | Level 6

Hallo Heide,

 

Kurt hat Problem und Lösung schon beschrieben, wenn Du SAS 9.4 hast, kannst Du call execute() einfach durch rc = dosubl() ersetzen, dann werden Makro und data step ein einem zweiten Thread abgearbeitet und Du sieht das gewünschte Ergebnis.

Denn zweiten Schritt mit open()/close() kannst Du Dir dann ebenfalls sparen, da die neue Makrovariable SYSNOBS nach Ausführen des Datastep die Anzahl der gefundenen Observations enthält.

 

%macro test(id=);
   data datenauszug;
      set daten(where=(id=&id));
   run;
   %if &&sysnobs > 0 %then %do;
      %put 'hallo -> ' &sysnobs;
   %end;
%mend test;

data _null_;
   set user;
   rc=dosubl('%test(id='!!id!!')');
run;

Hoffe, das hilft weiter, viele Grüße,

 

Grischa

HeideTribius
Fluorite | Level 6

hallo Ihr zwei,

 

herzlichen Dank! Es funktioniert hervorragend!

 

Ich hätte Euch eher fragen sollen...

JMS
Obsidian | Level 7 JMS
Obsidian | Level 7

Je nach Anwendung kannst du auch machen:

 

proc sql; select id,count(id) from daten group by id; run;

 

oder

 

proc sql; select id,count(id) into mid,mcount separated by ',' from daten group by id; run;

%put ∣

%put &mcount;