Kombinatorik
Verfasst von E_Berger am 21 November, 2008 - 12:03
Hallo zusammen !
Kann mir jemand sagen ob es in SAS die Möglichkeit gibt, bzw. wie man sich alle möglichen k-elementigen Teilmengen aus einer n elementigen Grundgesamtheit erstellt?
Beispiel:
Aus der Grundgesamtheit A B C D E sollen alle möglichen 3-elementigen Mengen gebildet werden. Mit Hilfe der Kombinatorik [ (n über k)=n!/(n-k)! * k!] kann man errechnen, dass es 10 Möglichkeiten gibt . ABC ABD …etc.
Weiß jemand Rat?
Gruß und schönes Wochenende
Eric Berger
»
- Anmelden oder Registrieren um Kommentare zu schreiben

Hallo, es ist auf jeden Fall
Hallo,
es ist auf jeden Fall möglich dies mit einem Makro zu programmieren. Eine fertige Funktion/Prozedur gibt es dafür meines Wissens nicht.
Ich habe ein solches Makro auch schon mal benutzt, ich weiß aber nicht, ob ich es frei veröffentlichen darf.
Gruß
Simon
Danke für die Info! Ich
Danke für die Info! Ich dachte, das es vielleicht in irgend einer Prozedur schon realisiert sei. Also an die Tasten......
Schönes Wochenende
Eric Berger
Vielleicht helfen Ihnen
Vielleicht helfen Ihnen diese Links schneller weiter. Habe nur kurz draufgeguckt, klingt aber vielversprechend.
Das scheint spannend zu
Das scheint spannend zu sein. Danke!!!
Lösungs-Voschlag
Hallo,
ich hatte vor einiger Teit ein ähnliches Problem und habe über redscope eine prima Lösung erhalten.
Diese Lösung von damals habe ich geringfügig erweitert und schon gibt es eine brauchbare Lösung für diese neue Frage. Was mir besonders gefällt ist, dass die von mir hier vorgstellte Lösung ohne doppelt und dreifach geschachtelte Schleifen auskommt, dank dem
proc transposeund den Transpose-Spezialisten hier im Forum!, MaxAnz= /* Wenn MaxAnz= mit Zahl gefüllt, dann ist gemeint: */
/* Aus der Grundgesamtheit lt. "infile=" sollen alle */
/* möglichen "MaxAnz"-elementigen Mengen gebildet werden */
);
/*---------------------------------------------------------------------------------
* Spezial-Makro
* 20081201, Anpassung mit MaxAnz= für Kombinatorik
* 20070515, sehr schlanke Lösung mit PROC MEANS bzw. PROC SUMMARY
* 20070515, perfektionierte Bit-Fummelei
* 20070514, HornungW (Redscope), 6-fach geschachtelte DO-Schleife
* 20070510, Rekursive Lösung
*
* Aufruf-Beispiele:
* =================
* data beispiel1; Vorwärts eingeben, dann ist Ausgabe SCHÖN
* input string $ zahl ;
* datalines;
* Z77 373
* ZK77 160
* ZH77 255
* ZM73 214
* ZL71 179
* LS73 231
* ;
* run;
* %vektor(beispiel1);
*
* data beispiel2; RÜCKwärts eingeben, dann ist Ausgabe unschön
* input string $ zahl ;
* datalines;
* LS73 231
* ZL71 179
* ZM73 214
* ZH77 255
* ZK77 160
* Z77 373
* ;
* run;
* %vektor(beispiel2);
*
* data beispiel3; Grundmenge hat 5 Elemente
* input string $ zahl ;
* datalines;
* A 1
* B 1
* C 1
* D 1
* E 1
* ;
* run;
* %vektor( beispiel3
* , MaxAnz=3
* );
*------------------------------------------------------------------------------ */
%put NOTE: macro vektor(infile=&infile., MaxAnz=&MaxAnz. );
/*-------------------------------------------------------------------------------
* EINMAL auf 0 == OK setzen, als default:
*
*------------------------------------------------------------------------------ */
%let errcode=0; /* EINMAL auf 0 == OK setzen, als default */
/*-------------------------------------------------------------------------------
* Diverse Parameter prüfen (bevor die richtige Arbeit losgeht)
*-------------------------------------------------------------------------------*/
%if &errcode. eq 0 /* Wenn bisher alles OK */
%then %do;
%*macro isnum(xxx); /* MaxAnz REIN numerisch */
%let xxx=&MaxAnz.;
%let yyy=%sysfunc(translate(%bquote(&xxx.),' ','0123456789')); /* Tausche Ziffer gegen Blanc */
%if &yyy. eq %then %do;
%put INFO: Wert IST rein numerisch (Wert=&xxx.);
%put %substr(###INFO,4)%str(:) vektor, Wert für MaxAnz IST rein numerisch (Wert=&xxx.);
%end;
%else %do;
%put INFO: Wert ist NICHT rein numerisch (Char im Wert-Feld sind=&yyy.);
%let errcode=-1;
%put %substr(###ERROR,4)%str(:) vektor, Wert für MaxAnz ist NICHT rein numerisch (Char im Wert-Feld sind=&yyy., errcode=&errcode.);
%end;
%*mend isnum;
%end;
%put INFO: errcode=&errcode;
/*---------------------------------------------------------------------------------
* VOR der eigentlichen Arbeit
*
* Input-Daten umsetzen, nur wenn MaxAnz gefüllt, wenn KOMBINATORIK gewünscht:
* Aus der Grundgesamtheit A B C D E sollen alle möglichen 3-elementigen
* Mengen gebildet werden.
* Mit Hilfe der Kombinatorik [ (n über k)=n!/(n-k)! * k!] kann man errechnen,
* dass es 10 Möglichkeiten gibt . ABC ABD …etc.
* Diese 10 Möglichkeiten werden mit proc print ausgegeben
*------------------------------------------------------------------------------ */
%if &errcode. eq 0 /* Wenn bisher alles OK */
%then %do;
data WORK.&infile.;
set &infile.;
%if &MaxAnz. ne
%then %do;
zahl=1;
%end;
run;
%end;
/*------------------------------------------------------------------------------
* Jetzt die eigentliche Arbeit
* -->> Input-Daten umbauen: ... (transpose)
* -->> Ergebins-Data-Set aufbauen: Jede mögliche Kombination erzeugen
* -->> Ergebins-Data-Set ausgeben: Jede mögliche Kombination als LST ausgeben
*------------------------------------------------------------------------------- */
*proc contents data=&infile.; run;
%if &errcode. eq 0 /* Wenn bisher alles OK */
%then %do;
proc transpose data=&infile. out=bbb(drop=_name_);
var zahl;
id string;
run;
%put INFO: VarList(bbb)=%VarList(bbb); /* Macro VarList in org.redscope.HansKneilmann.varlist */
proc summary data=bbb;
class %VarList(bbb);
var %scan(%VarList(bbb),1); /* Macro VarList in org.redscope.HansKneilmann.varlist */
output
sum(%scan(%VarList(bbb),1))=sum
out=ccc(drop=_type_ _freq_ sum)
;
run;
%end;
/*-------------------------------------------------------------------------------
* -->> Ergebnis-Data-Set ausgeben: Jede mögliche Kombination als LST ausgeben
* rownum hinzufügen für umsortieren
* Umsortieren für schönere Ausgabe (und rownum löschen)
* Ausgabe-Reihenfolge = Rückwärts = schöner
*------------------------------------------------------------------------------- */
%if &errcode. eq 0 /* Wenn bisher alles OK */
%then %do;
options missing=' ';
data ddd;
set ccc;
rownum=_N_;
run;
proc sort data=ddd out=eee(drop=rownum);
by descending rownum; /* Umsortieren für schönere Ausgabe */
run;
proc print data=eee noobs;
%if &MaxAnz. ne
%then %do;
%let VarListK=%VarList(bbb);
%let VarListK=%sysfunc(translate(%bquote(&VarListK.), "%str(,)"," ")); /* Tausche Blanc gegen , */
%put INFO: VarListK=&VarListK.;
where 1 <= sum(&VarListK.) <= &MaxAnz.;
%end;
run;
%end;
title2 " ";
%put INFO: Macro &SYSMACRONAME., Ende;
%mend vektor;
Wenn man die Eingabe-Datei passend macht (siehe Beispiel 3), dann erhält man z.B. alle "3 aus 5"-Konmbinationen.
Und das beste ist: Es gibt kein Problem mit "(...)weiß aber nicht, ob ich es frei veröffentlichen darf."
Gruß
Hans Kneilmann, Schäfer Shop (SSI)