die Lag() Funktion

hallo liebe Leute,

ich habe schon gehört, dass manche die Lag() Funktion meiden.

Ich weiss nur, dass man sie nicht benutzen sollte in Verzweigungen. Seht Ihr generelle Anwendungsprobleme bei der Lag-Funktion? Andersrum, gibt es eine echte Alternative?

Viele Grüsse
Dirk E.

Lag() ist gut

Das einzige Problem, das ich kenne, ist tatsachlich, dass man leicht einen Denkfehler macht, wenn man lag() in bedingten Anweisungen verwendet. Und vielleicht noch, dass es am Anfang fehlende Werte erzeugt, aber das liegt in der Natur der Sache. Ich füge hier mal den Link auf die Doku ein.

Es gibt die Alternative mit RETAIN, aber die ist sehr umständlich:

DATA rein;
   
INPUT zeile var1 $;
DATALINES;
1 AAA
2 BBB
3 CCC
4 DDD
5 EEE
6 FFF
;

DATA raus1;
   
SET rein;
   lag_var1 = lag(var1);
RUN;
stattdessen kann man auch schreiben:
DATA raus2;
   
SET rein;
   
RETAIN lag_var1;
   
OUTPUT;
   lag_var1 = var1;
RUN;
Wenn man Lag<N> verwendet, wird es noch komplizierter:
DATA raus3;
   
SET rein;
   lag3_var1 = lag3(var1);
RUN;
stattdessen kann man auch schreiben:
DATA raus4;
   
SET rein;
   
RETAIN lag1_var1 lag2_var1 lag3_var1 '   ';
   
DROP lag1_var1 lag2_var1;
   
OUTPUT;
   lag3_var1 = lag2_var1;
   lag2_var1 = lag1_var1;
   lag1_var1 = var1;
RUN;

Ein Beispiel mit IF...

Ein Beispiel für ein (fehlerhaftes) Lag in einem IF-Statement:

Angenommen, ich habe in meinen Daten eine Variable "Flag" und will, falls diese den Wert 1 hat, den vorletzten Wert von Variable VarA, ansonsten den vorletzten Wert von VarB ermitteln:

DATA Work.Test;
   
INFILE DATALINES;
   
INPUT Flag VarA VarB;
   
DATALINES;
1 3 4
0 5 7
1 9 11
0 13 15
1 17 19
0 25 33
RUN;

Dann könnte ich jetzt folgendes ausprobieren:

DATA Work.Falsch;
   
SET Work.Test;
   
IF (Flag EQ 1) THEN DO;
      Result = LAG2(VarA);
   
END;
   
ELSE DO;
      Result = LAG2(VarB);
   
END;
RUN;

Funktioniert so aber nicht (Das Programm läuft fehlerfrei, aber das Ergebnis ist nicht ganz das was man erwartet). Richtig ist z.B.:

DATA Work.Richtig(DROP=VorletzterA VorletzterB);
   
SET Work.Test;
   VorletzterA = LAG2(VarA);
   VorletzterB = LAG2(VarB);
   
IF (Flag EQ 1) THEN DO;
      Result = VorletzterA;
   
END;
   
ELSE DO;
      Result = VorletzterB;
   
END;
RUN;

Ein Blick in die Doku, siehe Link von Andreas, erklärt auch warum das so ist - LAG liefert nicht einfach den letzten (vorletzten, drittletzten, ...) Wert sondern arbeitet intern mit Warteschlangen.

Schöne Grüße
- MH -