Hallo,
ich habe folgenden Datensatz mit nur einer Variable x:
1 1 1 0 1 1 0 0 0 1 0 1 1
Wenn die Variable x=0 wird, soll die aktuelle und die folgende Beobachtung gelöscht werden (oder gekennzeichnet werden).
Allerdings soll die Regel auch auf die Folgebeobachtung angewendet werden.
Das Ergebnis soll dann so aussehen (D=löschen):
1 1 1 D D 1 D D D D D D 1
Wie kann ich das erreichen?
Danke!
Viele Grüße
Frank
Am einfachsten ist es sich zu merken, ob x=0 ist und dies dann in der Folgebeobachtung auszuwerten.
Hier ein Codebeispiel mit deinen Daten:
data test;
length x 8;
input x;
datalines;
1
1
1
0
1
1
0
0
0
1
0
1
1
;
run;
data cleaned;
length deleteflag 8;
retain deleteflag 0;
set test;
if (x eq 0) then do;
deleteflag = 1;
end;
else do;
/* Folgebeobachtung */
if not deleteflag then do;
output;
end;
deleteflag = 0;
end;
drop deleteflag;
run;
Gruß,
Andreas
Funktioniert super!
Vielen Dank.
Grüße
Frank
Hallo Andreas,
dummerweise habe ich eine Information vorenthalten und bin erst jetzt auf das Problem gestossen (weil mir immer Beobachtungen verschwanden..).
Es gibt noch eine Variable y , die die x gruppiert. Das Löschen der Folgebeaobachtung soll nur in der Gruppe stattfinden.
Also etwa so, die Gruppe 2 wird komplett gelöscht, aber 3 bleibt komplett erhalten.
Wie kann ich das erreichen?
data test;
length x 8;
input y x;
datalines;
1 1
1 1
1 1
1 0
1 1
1 1
2 0
2 0
2 0
2 1
2 0
3 1
3 1
;
run;
Hallo Frank,
dazu müsste dann die Gruppierungs-Variable noch geprüft werden.
Hier ein möglicher Ansatz:
Mit einem weiteren Retain könntest Du das y der vorherigen Zeile sichern und das dann in einer Bedingung zum Löschen, bzw. Setzen des "deleteflag" verwenden.
Alternativ gibt es auch die Möglichkeit mit einem "by y" zu arbeiten und dann die Prüfung, ob Du noch in der gleichen Gruppe bist mit lag(y) zu machen. Das gibt Dir dann das y der Vorzeile.
Wichtig ist in jedem Fall, dass die Daten vorher nach der Gruppierungs-Variable y sortiert sind.
Viele Grüße
Michael
Eine einfache BY Group Verarbeitung und die Prüfung per FIRST.Variablenname sollte das Problem lösen:
data cleaned;
length deleteflag 8;
retain deleteflag 0;
set test;
by y;
if (first.y) then do;
/* delete flag für jede neue Gruppe zurücksetzen */
deleteflag = 0;
end;
if (x eq 0) then do;
deleteflag = 1;
end;
else do;
/* Folgebeobachtung */
if not deleteflag then do;
output;
end;
deleteflag = 0;
end;
drop deleteflag;
run;
Viele Grüße,
Andreas
Hallo Andreas, hallo Michael,
gestern abend habe ich mit dem LAG Befehl experimentiert (den ich noch nie benutzt habe) ... und bin auf folgende Lösung gekommen. Ergebnis stimmt.
Habe ich richtig gedacht oder doch wieder irgendwo ein Ei gelegt?
Danke und viele Grüße
Frank
data test;
length x 8;
input zaehler y x;
datalines;
1 1 1
2 1 1
3 1 1
4 1 0
5 2 1
6 2 1
7 2 0
8 2 0
9 2 0
10 3 1
11 3 0
12 3 1
13 3 1
14 4 0
15 4 1
16 4 1
17 4 0
18 4 1
19 4 1
20 4 1
;
run;
data cleaned;
length deleteflag 8;
retain deleteflag 0;
set test;
ylag = lag(y);
if (x eq 0) then do;
deleteflag = 1;
end;
else do;
/* Folgebeobachtung */
if y ne ylag and deleteflag=1 then deleteflag=0;
if not deleteflag then output;
deleteflag = 0;
end;
drop deleteflag;
run;
Man muss bei der LAG()-Funktion immer im Auge behalten, dass sie ihren Speicher nur füllt, wenn sie aufgerufen wird. Daher ist es in der Regel falsch, sie innerhalb eines if oder einer do-Schleife zu verwenden.
Hallo zusammen,
Frank, das sieht doch gut aus - ich kann keine Fehler erkennen. (ylag würde ich noch droppen)
Persönlich würde ich mir jetzt das Length-Statement sparen. Das hat hier für mich einen deklarierenden Character, der meiner Ansicht nach nicht nötig ist, weil durch das Retain die Variable doch auch numerisch (Standard Länge 😎 aufgebaut wird.
Schöne Grüße
Michael
Ja, stimmt .... über das drop hatte ich nachgedacht, war nicht sicher und habe es dann vergessen.
Also jetzt mit Schönheitskorrekturen:
data test;
input zaehler y x;
datalines;
1 1 1
2 1 1
3 1 1
4 1 0
5 2 1
6 2 1
7 2 0
8 2 0
9 2 0
10 3 1
11 3 0
12 3 1
13 3 1
14 4 0
15 4 1
16 4 1
17 4 0
18 4 1
19 4 1
20 4 1
;
run;
data cleaned;
retain deleteflag 0;
set test;
ylag=lag(y);
if (x eq 0) then
do;
deleteflag=1;
end;
else
do;
/* Folgebeobachtung */
if y ne ylag and deleteflag=1 then
deleteflag=0;
if not deleteflag then
output;
deleteflag=0;
end;
drop deleteflag;
drop ylag;
run;
Hallo, Frank,
wenn TEST nach Y sortiert ist und X keine Missings enthält, lässt sich die Selektion m. E. noch weiter vereinfachen:
data cleaned;
set test;
by y;
if x & (lag(x) | first.y);
run;
Ein Satz wird also genau dann ausgegeben, wenn
Viele Grüße
Reinhard
Wenn Sie die Funktion lag, kodieren sie bitte wie dassr queue Funktion.
Die lag von SQL bekannt, aber reagiert ganz anders. Deshalb ist es oft falsch.
Doch mit diesem Hintergrundwissen, dann kann man es hochgenaue und bequem nutzen.
http://rosettacode.org/wiki/Queue/Definition
Danke nochmal allen für die Vorschläge!
Es hat mich gut weitergebracht 😉
Frank
Don't miss out on SAS Innovate - Register now for the FREE Livestream!
Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.