BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
dwarden3
Fluorite | Level 6

Hello,

 

I am trying to code all of the permutations of given length such that I get the following in one dataset: 

a

b

c

..............

a a 

a b

b a

.............

a a a 

a a b

a a c

a a d

a a e

...........

etc. 

 

Is there a way to do this iteratively in either base SAS or IML? I am able to make this using repetition in IML. 

 

 

 

Current code example (but repeated out to however many times):

proc IML;
c_num=repeat(1,5);
perm1=T(1:5);
p_num=T(1:5);
index=T(1:5);
create OutData1_org var {c_num, perm1, p_num, index}; /* create Work.OutData for writing */
append; /* write data in x and y */
close OutData1_org;

data OutData1;
set OutData1_org;
format perm $18.;
perm=cats(perm1);
drop perm1;
run;

proc IML;
a=T(1:5);
c_num=repeat(2,25);
perm1=repeat(a, {5 5 5 5 5});
perm2=repeat(1:5,5);
p_num=T(6:30);
index=T(1:25);
create OutData2_old var {c_num, perm1, perm2,p_num, index}; /* create Work.OutData for writing */
append; /* write data in x and y */
close OutData2_old;

data OutData2;
set OutData2_old;
perm_test=put(perm1,$1.)||" "||put(perm2,$1.);
perm=put(perm_test, $18.);
drop perm1 perm2 perm_test;
run;

 

data Perms;
set OutData1 OutData2;
run;

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

I see. You don't want permutations nor do you want combinations. You are looking for the Cartesian product of a set with itself k times, where k=1,2, and 3.  In the SAS/IML language, you can form a Cartesian product by using the ExpandGrid function.

 

If you want to write this information to a rectangular data set, you need to decide how to combine the results that only have 1 column (k=1) with the results that have two or three columns (k=2 and k=3). In the following program, I used missing values for the columns that are not used.

 

proc iml;
set = T( 0:5 );
/* generate all possible triplets (x1,x2,x3) where the x_i are in {0,1,2,3,4,5} */
p1 = set;
p2 = expandgrid(set, set);
p3 = expandgrid(set, set, set);


/* write to data set */
create Values var {Length, x1, x2, x3};

N = nrow(p1); /* N = 6 */
Length=j(N,1,1);
x1 = p1;  x2=j(N,1,.); x3=j(N,1,.); 
append;

N = nrow(p2); /* N = 6**2 = 36  */
Length=j(N,1,2);
x1 = p2[,1];  x2=p2[,2]; x3=j(N,1,.); 
append;

N = nrow(p3); /* N = 6**3 = 216 */
Length=j(N,1,3);
x1 = p3[,1];  x2=p3[,2]; x3=p3[,3];
append;

close;
quit;

View solution in original post

8 REPLIES 8
Rick_SAS
SAS Super FREQ

Do you want permutations or combinations? Run the following program, which shows how to get all permutation (by using the ALLPERM function) or all combinations of k elements (by using the ALLCOMB function):

 

proc iml;
set = 1:3;
/* generate all permutations of 3 elements */
p = allperm(set);
print p;

/* if you want letters, index into the set {A, B, C} */
letters = {A B C};
p2 = letters[p];
p3 = shape(p2, 0, 3);
print p3;

/* generate all combination of 3 elements taken k at a time */
do k = 1 to 3;
   ck = allcomb(3, k);
   print "----" k "----", ck;
end;

For more information, see

 

dwarden3
Fluorite | Level 6

Hi Rick, 

 

Set p you made is correct except I also need: 000, 111, 444 etc. and things like 501,432, etc. I want all of the possible combinations that are x long from y items (0 to 5). 

 

So when the set is length 1, I would have: 0, 1, 2, 3, 4, 5.

With two: 0 0, 0 1, 0 2 ,0 3, 0 4, 0 5, 1 0 , 1 1, etc. 

 

Thank you

Rick_SAS
SAS Super FREQ

I see. You don't want permutations nor do you want combinations. You are looking for the Cartesian product of a set with itself k times, where k=1,2, and 3.  In the SAS/IML language, you can form a Cartesian product by using the ExpandGrid function.

 

If you want to write this information to a rectangular data set, you need to decide how to combine the results that only have 1 column (k=1) with the results that have two or three columns (k=2 and k=3). In the following program, I used missing values for the columns that are not used.

 

proc iml;
set = T( 0:5 );
/* generate all possible triplets (x1,x2,x3) where the x_i are in {0,1,2,3,4,5} */
p1 = set;
p2 = expandgrid(set, set);
p3 = expandgrid(set, set, set);


/* write to data set */
create Values var {Length, x1, x2, x3};

N = nrow(p1); /* N = 6 */
Length=j(N,1,1);
x1 = p1;  x2=j(N,1,.); x3=j(N,1,.); 
append;

N = nrow(p2); /* N = 6**2 = 36  */
Length=j(N,1,2);
x1 = p2[,1];  x2=p2[,2]; x3=j(N,1,.); 
append;

N = nrow(p3); /* N = 6**3 = 216 */
Length=j(N,1,3);
x1 = p3[,1];  x2=p3[,2]; x3=p3[,3];
append;

close;
quit;
dwarden3
Fluorite | Level 6
Thank you so much! I knew there was a way to do this with IML.
ErikLund_Jensen
Rhodochrosite | Level 12

Hi @dwarden3 

 

Here are two other ways, both in base SAS:

 

* Data Step
  Permutations as iterations over letter array and concatenation of elements;
data test1 (drop=letter: i j k);
  length permutation $3;
  array letter {3} $ ('A','B','C');
  do i = 1 to 3;
    do j = 1 to 3;
      do k = 1 to 3;
        permutation = catt(letter{i},letter{j},letter{k});
        output;
      end;
    end;
  end;
run;


* Proc SQL 
  Permutations as cartesian products of joining letter data set and concatenation of elements;
proc sql;
  create table t1 (letter char(1));

  insert into t1 
    set letter = 'A'
    set letter = 'B'
    set letter = 'C';

  create table t2 as
    select catt(a.letter,b.letter) as permutation
    from t1 as a, t1 as b;

  create table test2 as
    select catt(a.permutation,b.letter) as permutation
    from t2 as a, t1 as b;
quit;

 

 

yabwon
Onyx | Level 15

Some time ago I did this macro (tested up to 13), maybe you find it useful:

proc format;
  value perm
    1  = A
    2  = B
    3  = C
    4  = D
    5  = E
    6  = F
    7  = G
    8  = H
    9  = J
    10 = J
    11 = K
    12 = L
    13 = M
    other = "X"
  ;
run;
 
%macro perm(level,print=1);
  %do level = 1 %to &level.;
    %if 1 = &level. %then
      %do;
        data _1;
          _1_1 = 1;
        run;
      %end;
    %else
      %do;
        data _&level.;
          set _%eval(&level. - 1);
          array old[*] _%eval(&level. - 1)_:;
          array new[&level.] _%eval(&level.)_1 - _%eval(&level.)_&level.;
 
          do j = 1 to &level.;
            new[j] = &level.;
            do k = 1 to %eval(&level. - 1);
              new[k+(k>=j)] = old[k];               
            end;
            output;
          end;
        keep _%eval(&level.)_:;
        run;
 
        proc delete data = _%eval(&level. - 1);
        run;
      %end;
  %end;
 
  %if 1 = &print. %then
    %do;
      proc sort data = _%eval(&level. - 1);
        by _all_;
      run;
      proc print data = _%eval(&level. - 1);
        format _all_ perm.;
      run;
    %end;
%mend perm;
 
%perm(5);
 
%perm(8,print=0);

If you comment out:

        proc delete data = _%eval(&level. - 1);
        run;

you will get all intermediate datasets.

 

[EDIT:]

Format _perm_ is just for print out, but you can easily modify final dataset with it.

 

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Ksharp
Super User
%macro perm(n=);
proc plan seed=12345 ;
%do i=1 %to &n.;
factors
 %do j=1 %to &i.;
   x&j.=&n. perm
 %end;
/noprint;
output out=x&i.;
run;
%end;
quit;

data want;
 set x1-x&n.;
run;
%mend;


%perm(n=5)
Tom
Super User Tom
Super User

What you show as output does not look at all like a dataset.  Datasets have a fixed number of variables.  You cannot have 3 rows with only one variable and then another three rows with 2 variables.

 

So what form do you want the output to take?

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 1232 views
  • 1 like
  • 6 in conversation