2015-03-30 16 views
5

W SAS jeśli mam ciąg lub tablicy jak poniżej,Generowanie wszystkie unikalne permutacji tablicy w SAS

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

muszę wygenerować wszystkie „unikalne” permutacje elementów jak poniżej,

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

Czy w SAS istnieje funkcja generowania wszystkich możliwych kombinacji macierzy?

+3

Myślę, że jest to połączenie zamiast permutacji. – Lovnlust

+0

'AB' i' BA' to różne permutacje, ale ta sama kombinacja. – MatBailie

+0

Na pytanie to było pytanie o kod. Pytanie o to, co zredagowałem, jest bardziej akceptowalne. – Joe

Odpowiedz

3

Założenie: Wierzę szukasz combinations i nie permutations, więc kolejność nie ma znaczenia, BA i AB to samo.

Użyj funkcji podprogramu call allcomb i comb, aby znaleźć możliwe kombinacje.

Przeczytaj więcej o allcomb i comb tutaj

i tutaj

W Shor t -

  • call allcomb podprogram daje możliwe kombinacje Spośród n elementów podczas r z nich są podejmowane i
  • comb funkcja daje ilu kombinacje byłoby gdy z n elementów r z nich są podejmowane na czas.

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

Dzięki @NEOmen. Na pewno się tym zajrzę. Wydaje się, że to powinno być w stanie wygenerować to, co chcę. – babsdoc

2

Oto krótki skrypt, który znajdzie kombinacje poszczególnych postaci ciągu znaków. Można to łatwo zaadaptować do pracy z tablicami, jeśli wolisz. Zamiast używać funkcji kombinacyjnych i procedur wywoływania (,, lex*, ran*) podejście to tworzy permutacje za pomocą binarnej reprezentacji liczb całkowitych do 2**len. Preferuję to podejście, ponieważ uważam, że demonstruje to, co się dzieje, jest bardziej przejrzyste i nie zmienia kolejności przydziałów tablicowych.

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; 

Jeśli zrobić chcą permutacje następnie similar approach jest możliwe przy użyciu factoradic reprezentacje liczb.Zalecam jednak użycie funkcji kombinowanej, ponieważ konwersje byłyby znacznie bardziej zaangażowane. Prawdopodobnie jest to całkiem fajne ćwiczenie kodowania do nauki.


Byłoby świetnie, gdyby SAS miał funkcję zmniejszania ciągów według wzorców logicznych, ale prawdopodobnie nie miałoby dużego zastosowania.

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

Dzięki @SRSwift. To jest najbardziej odmienny sposób robienia tego. Nikt mi nawet tego nie zasugerował, ale ma sens i wygląda interesująco, też go wypróbuję. – babsdoc

3

Nieco inne podejście do tego jest użycie proc summary.

Utwórz sztuczny zestaw danych. Przypisać każdy element tablicy do zmiennej, dzięki czemu możemy karmić go do proc summary:

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

Uruchom proc summary.

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

Można również użyć ways lub types oświadczenia w proc summary aby ograniczyć wszelkie kombinacje można chcieć.

Interesującym efektem ubocznym tego jest to, że dostajemy również kolumnę _type_ w zbiorze danych wyjściowych. W powyższym przykładzie, następujące wartości przypisuje:

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

Tak więc, jeśli wartość w zbiorze wyjściowym _type_ wynosi 13, to wie, że rząd został wytworzony przez połączenie A, B i D (8 + 4 + 1).

+2

+1 Bardzo ładne. Jestem tak przyzwyczajony do używania 'nway', że często zapominam o grupowaniu klas. Nie sądzę, abyś potrzebował 'var',' sum', 'manekina' lub dowolnej z opcji, domyślne zachowanie z' class' i 'output out' powinno dać pożądany wynik. – SRSwift

+0

Dzięki Robert. Nigdy wcześniej nie korzystałem z profesjonalnego podsumowania. Na pewno spróbuję tego. – babsdoc

+1

@SRSwift Dobre punkty - zaktualizowałem kod na podstawie twoich sugestii, dziękuję. –