2015-03-30 13 views
5

In SAS, wenn ich einen String oder ein Array wie die folgenden haben,generieren Alle Einzigartige Permutationen eines Arrays in SAS

array x[4] $1 ('A' 'B' 'C' 'D'); 

Ich brauche alle „Unique“ Permutationen der Elemente wie die folgenden zu erzeugen,

[ABCD] 
[ABC] 
[BCD] 
[ACD] 
[ABD] 
[AB] 
[AC] 
[AD] 
[BC] 
[BD] 
[CD] 
[A] 
[B] 
[C] 
[D] 

Gibt es in SAS eine Funktion zum Generieren aller möglichen Kombinationen des Arrays?

+3

Ich denke, das ist Kombination statt Permutation. – Lovnlust

+0

'AB' und' BA' sind unterschiedliche Permutationen, aber die gleiche Kombination. – MatBailie

+0

Wie gefragt wurde nach Code gefragt. Die Art und Weise zu fragen, die ich bearbeitet habe, ist akzeptabler. – Joe

Antwort

3

Annahme: Ich glaube, Sie suchen combinations und nicht permutations, so dass die Reihenfolge keine Rolle spielt, BA und AB gleiche Sache sind.

Verwenden Sie call allcomb Unterroutine und comb Funktion, um die möglichen Kombinationen zu ermitteln.

Lesen Sie mehr über allcomb und comb hier

und hier

In Shor t -

  • call allcomb Unterprogramm gibt die möglichen Kombinationen aus n Elemente, wenn r von ihnen genommen und
  • comb Funktion gibt an, wie viele Kombinationen es wäre, wenn sie aus n Elemente r von ihnen bei einem genommen werden Zeit.

data test(keep=my_string); 
length my_string $50.; 
    array a[4] $ ('A' 'B' 'C' 'D'); 

    n = dim(a); 

    do k=1 to n; 
     do j=1 to comb(n,k); 
      call allcomb(j,k,of a[*]); 
       do i = 1 to k; 
        if i=1 then do; my_string="";counter=0;end; 
        counter=counter+1; 
        my_string=cat(compress(my_string),compress(a[i])); 
       if counter=k then output; 

       end; 
      end; 
    end; 
run; 
+0

Danke @NEOmen. Ich werde das sicherlich untersuchen. Scheint so sein zu können, was ich will. – babsdoc

2

Hier ist eine schnelle Skript, das die Kombinationen der einzelnen Zeichen innerhalb einer Zeichenfolge finden. Dies könnte leicht angepasst werden, um mit Arrays zu arbeiten, wenn Sie bevorzugen. Anstatt die kombinatorischen Funktionen und Aufrufroutinen (all*, lex*, ran*) zu verwenden, werden bei diesem Ansatz die Permutationen mithilfe der binären Darstellung von ganzen Zahlen bis 2**len erstellt. Ich bevorzuge diesen Ansatz, da ich denke, dass er zeigt, was passiert, transparenter ist und die Reihenfolge der Array-Zuweisungen nicht ändert.

data have; 
    str = "123456"; output; 
    str = "ABCD"; output; 
run; 
data want; 
    set have; 
    length comb $20.; 
    len = length(str); 
    /* Loop through all possible permutations */ 
    do _i = 0 to 2**len - 1; 
     /* Store the current iteration number in binary */ 
     _bin = putn(_i, "binary" || put(len, best.) || "."); 
     /* Initialise an empty output variable */ 
     comb = ""; 
     /* Loop through each value in the input string */ 
     do _k = 1 to len; 
      /* Check if the kth digit of the binary representation is 1 */ 
      /* And if so add the kth input character to the output */ 
      if substr(_bin, _k, 1) = "1" then 
       comb = cats(comb, substr(str, _k, 1)); 
     end; 
     output; 
    end; 
    /* Clean up temporary variables, commented so you can see what's happening */ 
/* drop _:; */ 
run; 

Wenn Sie wollen Permutationen tun dann ein similar approach möglich ist factoradic Darstellungen der Zahlen.Aber ich würde empfehlen, dass Sie stattdessen eine kombinatorische Funktion verwenden, da die Konvertierungen viel mehr beteiligt wären. Es ist wahrscheinlich eine ziemlich gute Programmierübung zum Lernen.

Es wäre großartig, wenn SAS eine Funktion zum Reduzieren von Strings durch boolesche Muster hätte, aber es würde wahrscheinlich nicht viel Nutzen bringen.

bsubstr("ABCD", "1010") --> "AC" 
bsubstr("ABCD", "1110") --> "ABC" 
bsubstr("ABCD", "0001") --> "D" 
+0

Danke @SRSwift. Dies ist die verschiedenste Art, dies zu tun. Niemand hat mir das vorgeschlagen, aber es macht Sinn und sieht interessant aus, ich werde es auch ausprobieren. – babsdoc

3

Ein etwas anderer Ansatz ist die Verwendung proc summary.

Erstellen Sie ein Dummy-Dataset. Vergeben jedes Element des Arrays zu einer Variablen, so dass wir sie in proc summary ernähren:

data tmp; 
    array arr[*] a b c d (1 1 1 1); 
run; 

Run proc summary.

proc summary data=tmp noprint missing; 
    class a b c d; 
    output out=combinations; 
run; 

Sie können auch die ways oder types Aussagen in proc summary verwenden, um alle Kombinationen zu begrenzen Sie möchten.

Jetzt der interessante Nebeneffekt dabei ist, dass Sie die Spalte auch im Ausgabe-Dataset erhalten. In dem obigen Beispiel den folgenden Werten würde zugewiesen werden:

D = 1 
C = 2 
B = 4 
A = 8 

Wenn also der _type_ Wert in dem Ausgangsdatensatz 13 ist, dann wissen wir, dass die Zeile durch die Kombination A, B und D (8 + 4 generiert wurde + 1).

+2

+1 Sehr nett. Ich bin so daran gewöhnt, 'nway' zu verwenden, dass ich oft die Klassengruppierung vergesse. Ich glaube nicht, dass Sie die 'var',' sum', 'dummy' oder irgendeine der Optionen benötigen, das Standardverhalten mit nur' class' und 'output' sollte die gewünschte Ausgabe ergeben. – SRSwift

+0

Danke Robert. Ich habe noch nie eine Profi-Zusammenfassung verwendet. Ich werde das definitiv versuchen. – babsdoc

+1

@SRSwift Gute Punkte - Ich habe den Code basierend auf Ihren Vorschlägen aktualisiert, danke. –

Verwandte Themen