Hallo zusammen,
ich habe eine csv-Datei in SAS importiert, die in der ersten Spalte eine ID enthält und in den restlichen Spalten 4-stellige Zahlen-Codes.
Ich möchte die Datensätze angezeigt bekommen, in denen 4-stellige Zahlen-Codes mehrfach vorkommen.
Beispiel:
1;0002;1235;3468;4587;3952;6795;
2;0136;5976;3290;0554;4281;3942;
3;3594;4381;4753;3954;0002;4753;
Hier sollte mir im Ergebnis nur noch die 3. Zeile angezeigt werden, da diese den zahlen-Code "4753" mehrfach enthält.
Ich habe schon probiert, die Daten erst mit proc transpose zu transponieren. Allerdings komme ich nicht wirklich weiter, weil die Datei über eine Million Datensätze hat.
Vielen Dank vorab und viele Grüße
Katrin
Bitte probier mal das:
data have;
infile datalines dlm=";";
input (id c1-c6) ($);
datalines4;
1;0002;1235;3468;4587;3952;6795;
2;0136;5976;3290;0554;4281;3942;
3;3594;4381;4753;3954;0002;4753;
;;;;
proc transpose data=have out=long (rename=(col1=code));
by id;
var c:;
run;
data want;
set long;
by id;
retain ind list;
length list $50.;
if first.id
then call missing(ind,list);
if index(list,strip(code)) then ind = 1;
list = catx(";",list,code);
if last.id and ind;
keep id;
run;
Ein transpose wide to long sollte eigentlich kein Problem darstellen.
Ausnahmsweise mal eine Lösung ohne tranpose:
data have;
length id $ 10 var1-var6 $ 4;
infile datalines4 delimiter=';';
input ID var1-var6;
datalines4;
1;0002;1235;3468;4587;3952;6795
2;0136;5976;3290;0554;4281;3942
3;3594;4381;4753;3954;0002;4753
;;;;
data want;
set have;
length alle $ 40;
array werte var:;
alle = catx('|', of var:);
do i = 1 to dim(werte)-1;
if count(alle, trim(werte[i])) > 1 then do;
output;
leave;
end;
end;
drop i alle;
run;
Hallo Katrin,
folgender Code sollte funktionieren, geht sicherlich noch eleganter.
data in;
infile datalines;
input id $ a $ b $ c $ d $ e $ f $;
datalines;
1 0002 1235 3468 4587 3952 6795
2 0136 5976 3290 0554 4281 3942
3 3594 4381 4753 3954 0002 4753
;
run;
data in2 ;
set in;
if
a = b or
a = c or
a = d or
a = e or
a = f or
b = a or
b = c or
b = d or
b = e or
b = f or
c = a or
c = b or
c = d or
c = e or
c = f or
d = a or
d = b or
d = c or
d = e or
d = f or
e = a or
e = b or
e = c or
e = d or
e = f or
f = a or
f = b or
f = c or
f = d or
f = e ;
run;
Viele Grüße
Bernd
Hallo @Katrin11,
mit einer Perl Regular Expression geht es auch:
data have;
infile cards dlm=';';
input ID (code1-code6)(:$4.);
cards4;
1;0002;1235;3468;4587;3952;6795;
2;0136;5976;3290;0554;4281;3942;
3;3594;4381;4753;3954;0002;4753;
;;;;
data want;
set have;
if prxmatch('/(\d{4}).+\1/',catx('#',of code:));
run;
Edit:
Erläuterung: Die CATX-Funktion verkettet die sechs Codes mit einem beliebig gewählten Trennzeichen, z. B. zu 3594#4381#4753#3954#0002#4753. Dann sucht die PRXMATCH-Funktion in diesem String nach vier aufeinanderfolgenden Ziffern (dafür steht "\d{4}"), nach denen mindestens ein weiteres Zeichen (".+") sowie erneut die zuvor gefundenen vier Ziffern ("\1") folgen. Da die Codes alle vierstellig sind, muss es sich bei dem zweiten "Treffer" ggf. um einen wiederholten Code handeln. Der Rückgabewert der PRXMATCH-Funktion ist dann die Zeichenposition des ersten der doppelten Codes, im Beispiel also 11 (allgemein: eine Zahl >0), und der betreffende Satz wird ausgegeben. Tritt kein Code doppelt auf, ist der Rückgabewert 0 und die IF-Bedingung damit nicht erfüllt, so dass der Satz nicht ausgegeben wird.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!