Community deutschsprachiger SAS-Anwender und -Programmierer

Antworten
Dies ist eine offene Gruppe. Melden Sie sich an und klicken Sie auf die Schaltfläche „Gruppe beitreten“, um Mitglied zu werden und damit zu beginnen, Beiträge in dieser Gruppe zu veröffentlichen.
Highlighted
Contributor
Beiträge: 30
DO Loop mit Makro

Hallo zusammen,

 

vielleicht hat jemad einen Hinweis für mich, wie man mein Problem am elegantesten lösen kann.

Ich habe allerdings noch keinen vernünftigen Ansatzpunkt :-(

Beispieldatensatz:

nr test1 test2

1 0 1

1 1 1

1 0 0

3 1 0

3 1 0

3 0 1

4 0 0

4 0 1

4 1 1

 

Aus diesem Datensatz will ich die mit gleicher nr "herausnehmen" und an ein makro übergeben, was mir Sensitivität, PPV usw. berechnet. Solange, bis alle nr abgearbeitet sind.

Danke schon mal.

Viele Grüße

Frank

 

 

 

Esteemed Advisor
Beiträge: 5.954
Betreff: DO Loop mit Makro

Mit proc sort nodupkey eine Liste der Nummern erzeugen, und dann mit der einen data _null_ step "füttern" und mit call execute den Makro aufrufen.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Trusted Advisor
Beiträge: 1.114
Betreff: DO Loop mit Makro

Wenn das Makro unveränderbar vorliegt, ist der von Kurt Bremser skizzierte Ansatz sicher eine gute Lösungsmöglichkeit. Sollte das Makro dagegen Teil des zu entwickelnden Codes sein, würde ich es gleich so programmieren, dass es die Verarbeitung von BY-Gruppen beherrscht. Denn die gewünschten Berechnungen für den Beispieldatensatz würde man doch wahrscheinlich entweder in einem Datastep (mit set ...; by nr;) oder mit Hilfe von PROC FREQ (ebenfalls by nr;) durchführen. (Für letzteres, jedoch ohne BY-Gruppen, siehe http://support.sas.com/kb/24/170.html.)

Frequent Contributor
Beiträge: 108
Betreff: DO Loop mit Makro

Hallo Frank,

 

ich würde auch schauen, dass die Verarbeitung mit einem BY-Statement alle Datensätze abarbeiten kann.

 

 

Alternativ kann z.B. mit einem Hash immer ein entsprechendes Dataset erzeugt werden und mit Call-Execute in einem Macro verarbeitet werden.

Dabei könnten sogar die Ergebnisse anschließend im gleichen Data Step wieder eingelesen und an die Original-Daten angefügt werden.

(Hier findet sich unter "Splitting A SAS File Dynamically Using The .OUTPUT() Method" ein Ansatz dafür)

 

Ein anderer Ansatz wäre die Ausgangsdaten (mit einem Hash) dynamisch in einzelne Datasets zu zerlegen und in einem Macro alle erzeugten Datasets zu verarbeiten.

 

Das hängt natürlich davon ab, wie mit den Ergebnissen weiter verfahren werden soll. Werden einzelne Datasets gebraucht oder wieder ein großes Dataset, etc...

 

Herzliche Grüße

Michael

Contributor
Beiträge: 24
Betreff: DO Loop mit Makro

Hallo Frank,

 

mit einem Macro geht das folgendermaßen:

 

data _test;
input nr test1 test2;
cards;
1 0 1
1 1 1
1 0 0
3 1 0
3 1 0
3 0 1
4 0 0
4 0 1
4 1 1
run;
%macro loop_freq(data);
  %local i n values;
  
/* ermitteln der Nummern */ Proc sql noprint; select distinct nr into :values separated by " " from &data.; %let n = &sqlobs.; quit;
Title "Loop über Nr"; %do i = 1 %to &n.; /* Hier findet jetzt die Verarbeitung statt im Beispiel Freq*/ footnote "Verarbeitung von Nr: %scan(&values.,&i.,%str( ))"; Proc freq data = &data.; table test1*test2; where nr = %scan(&values.,&i.,%str( )); run; footnote; %end; title; %mend; ods html; %loop_freq(_test); ods html close;

Das funktioniert, solange alle Nummern in eine Macrovariable passen.

Anssonsten gibt es noch das bereits erwähnte Call execute und noch die Routine dosubl, die mithilfe des by-Statements aus dem Datastep aufgerufen werden können.

 

Viele Grüße

Jan

Contributor
Beiträge: 21
Betreff: DO Loop mit Makro

Hallo Frank,

 

eine einfache Möglichkeit ist, die Makroaufrufe erzeugen zu lassen und dabe den Wert für NR zu übergeben, so dass das Makro dann entsprechend filtern kann. hier ein einfaches Beispiel:

Data Work.Test;
Input nr test1 test2;
cards;
1 0 1
1 1 1
1 0 0
3 1 0
3 1 0
3 0 1
4 0 0
4 0 1
4 1 1
;
run;

%Macro calc(n);
  %Put NOTE: [calc] do anything with &n..;
%Mend;

%Global code;
Proc Sql noprint;
  Select Distinct cats('%calc(',nr,')') Into :code Separated By " "
    From Work.Test
  ;
Quit;

%Put NOTE: code=%superq(code);

&code

Das Makro %CALC erzeugt in diesem Falle lediglich eine Ausgabe in das LOG mit dem Wert von NR, das entscheidende ist der PROC SQL Step. Hier wird der Makroaufruf zusammengesetzt und in eine Makro-Variable gespeichert.. Der Inhalt wird mit %Put in das LOG ausgegeben, anschließend wird mit &CODE der String mit den Makroaufrufen an den Input-Stack übergeben.

 

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

 

Grischa

Contributor
Beiträge: 30
Betreff: DO Loop mit Makro

Vielen Dank für Eure Hilfe!

In den letzten Tagen habe ich mich dem Beispiel von Grischa beschäftigt und wieder mal einiges dazu gelernt :-)

Auf jeden Fall bin ich zum Ziel gekommen.

Die anderen Beispiele werde ich mir auch noch vornehmen, im Moment hapert's nur mit der Zeit.

 

Danke nochmal und herzliche Grüße

Frank