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
New Contributor
Beiträge: 3
Schleife mit Multiplikation über mehrere Zeilen
[ Bearbeitet ]

Hallo zusammen!

 

Ich möchte ein Produkt bilden über mehrere Zeilen im Datensatz hinweg.

Sobald eine Zeile mit einer neuen id auftritt, soll neu gerechnet werden.

 

Eine Summe schaffe ich zu berechnen, aber wenn ich das + gegen ein * tausche, erhalte ich eine Fehlermeldung.

 

Hier ein kurzes Beispielprogramm (die fehlerhafte Produktberechnung ist auskommentiert):

 

data test;
input id wert;
cards;
1 3
1 5
1 7
2 1
2 2
2 3
2 4
3 5
3 5
3 5
run;

Proc sort data=test;
by id wert;
run;


data test2;
 set test;
 by id;
 if first.id then do;
 summe = 0;
 summe = summe + wert;
 *produkt = 1;
 *produkt = produkt * wert;
 end;
 else do;
 summe + wert;
 *produkt * wert;
 end;
run;

 

 

Habt ihr eine Idee für mich, wie ich das hinkriege?
Vielen Dank vorab für Eure Hilfe!

Harald

Frequent Contributor
Beiträge: 121
Re: Schleife mit Multiplikation über mehrere Zeilen

Hallo Harald,

 

da du für die Multiplikation kein SUM Statement verwenden kannst, musst du die Variable produkt explizit per RETAIN Statement so deklarieren, dass ihr Wert über die Datensatziterationen erhalten bleibt.

 

Hier ein lauffähiges Beispiel:

 

data test2;
 set test;
 by id;
 retain produkt 0;
 if first.id then do;
   summe = 0;
   summe = summe + wert;
   produkt = 1; 
 end;
 else do;
   summe + wert;
 end;
 produkt = produkt * wert;
run;

Gruß,

Andreas

New Contributor
Beiträge: 3
Re: Schleife mit Multiplikation über mehrere Zeilen

Hallo Andreas,

 

vielen Dank für Deine schnelle Hilfe!

 

Gruß,

Harald

Occasional Contributor
Beiträge: 7
Re: Schleife mit Multiplikation über mehrere Zeilen

Hallo Harald,

 

summe+wert;

ist eine sogenannte SUM-Anweisung, die die Variable summe automatisch retained. Eine Entsprechende MAL-Anweisung gibt es leider nicht. Folgendermaßen funktioniert es:

 

 

data test2;
 set test;
 by id;
 retain produkt 1;
 if first.id then do;
  produkt = 1;
 end;
 produkt=produkt * wert;
run;

Wichtig dabei ist es die Variable produkt auf retain zu setzen, das bedeutet, dass der errechnete Wert beibehalten wird, bis er bei einem Gruppenwechsel (first.id) neu initialisiert wird.

 

 

Viele GRüße

Wolfgang

New Contributor
Beiträge: 3
Re: Schleife mit Multiplikation über mehrere Zeilen

Hallo Wolfgang,

 

vielen Dank für Deine schnelle Hilfe!

 

Gruß,

Harald

Contributor
Beiträge: 38
Re: Schleife mit Multiplikation über mehrere Zeilen
[ Bearbeitet ]

und zur Abwechslung mal etwas proc sql ;-)

Marius

 

data test;
	input id wert;
	cards;
1 3
1 5
1 7
2 1
2 2
2 3
2 4
3 5
3 5
3 5
run;

proc sql;
	SELECT
		id,
		round
	(CASE
		WHEN MinVal = 0 THEN 0
		WHEN mod(Neg, 2) = 1 THEN -1 * EXP(ABSMult)
		ELSE EXP(ABSMult)
	END)
as Mult_Wert
	from(
		SELECT
			id, 
			SUM(log(ABS(ifn(wert=0, 0,wert)))) AS ABSMult,
			SUM(SIGN
		(CASE 
			WHEN wert < 0 THEN 1 
			ELSE 0 
		END)
			) AS Neg,
			MIN(ABS(wert)) AS MinVal
		FROM
			test
		GROUP BY
			id
			) test
	;
quit;
Occasional Contributor
Beiträge: 7
Re: Schleife mit Multiplikation über mehrere Zeilen
[ Bearbeitet ]

Mit PROC SQL

 

DATA TEST;
  INPUT ID WERT;
  CARDS;
1 3
1 5
1 7
2 1
2 2
2 3
2 4
3 5
3 5
3 5
RUN;

PROC SQL;
  SELECT ID, 
         EXP(SUM(LOG(WERT))) AS PRODUKT
  FROM TEST
  GROUP BY ID;
QUIT;
Contributor
Beiträge: 38
Re: Schleife mit Multiplikation über mehrere Zeilen
Hi Dennis_V,

mal mit einem Wert von 0 getestet? ;-)

Viele Grüße
Marius
Trusted Advisor
Beiträge: 1.116
Re: Schleife mit Multiplikation über mehrere Zeilen

Auch wenn man nur positive Eingangswerte zulässt, sollte m. E. ein ROUND um das Formelergebnis nicht fehlen. Es könnte ja sein, dass mit der Variable PRODUKT weitergearbeitet wird (z. B. if produkt<125 then ...). Dann stellen die möglichen Rundungsfehler ein Risiko dar. Schon im vorliegenden Zahlenbeispiel weichen 2 der 3 Ergebnisse vom erwarteten ganzzahligen Produkt ab (jedenfalls auf meinem Rechner).

 

Werden prinzipiell auch nicht ganzzahlige Eingangswerte zugelassen, ist bei der Wahl der Rundungseinheit auf die Größenordnung der erwarteten Ergebnisse zu achten. In vielen Fällen ähnlich dem vorliegenden Beispiel dürfte sich 10^-8 als Rundungseinheit eignen, also

ROUND(EXP(SUM(LOG(WERT))), 1E-8) AS PRODUKT