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;
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;
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
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
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;
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;
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
%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)
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 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.