Hi everyone,
I am working on SAS/IML. I am trying to figure out the number of combinations of factors in factorial design as follows :
imagine we have 4 factors, A, B, C and D. I want to get the following:
1
A
B
AB
C
AC
BC
ABC
D
AD
BD
ABD
CD
ACD
BCD
ABCD
Basically the first four combinations (1, A, B, AB) are always the same for any number of factors (m) so I have put this in a matrix form as initial combinations:
ncomb = 2**(m);
print ncomb;
initial_combs = j(4,m,0);
initial_combs[2,1] = 1;
initial_combs[3,2] = 1;
initial_combs[4,1] = 1;
initial_combs[4,2] = 1;
print initial_combs;
I have used 0's and 1's to indicate the absence and presence of the factor respectively.
The I used the initial_comb matrix to add the following four combinations (C, AC, BC, ABC). All I have done is adding C to the initial combinations:
combs = j(4,m,0);
count = 3;
do i = 1 to 4;
do j = 1 to m;
if initial_combs[i,j] = 1
then combs[i,j] = initial_combs[i,j];
else combs[i,count] = 1;
end;
end;
combs = initial_combs // combs;
print combs;
Note; I have combined the initial_combs matrix with the new combs. If I had 3 factors I would stop here. As I had 4 factors I have to do another set of calculations:
combss = j(8,m,0);
count = 4;
do i = 1 to 8;
do j = 1 to m;
if combs[i,j] = 1
then combss[i,j] = combs[i,j];
else combss[i,count] = 1;
end;
end;
combss = combs // combss;
print combss;
In the last set, I have used the previous combined matrix (initial_combs with the new combs) and added D to the existing combinations. Again I had to combine the previous combinations (combs) with the new one (combss) to get the full set of combinations for m=4.
If I want to work out the combinations for m=5 I have to add another set of calculations.
Basically this will make the program very long. I need to combine all these separate sets of calculations into one loop maybe. The loop should depend on the number of factor (3, 4, 5,.....) I have tried to figure out how to do it but I couldn't. It is greatly appreciated if anyone could help
Thanks,
DJ
If the order of the rows of the matrix is not important then the problem is equivalent to counting in binary. For example
proc iml;
start FullFactorial( n );
r = 2 ## n;
x = j(r, n);
pot = 2 ## ( (n-1):0 );
do i = 1 to r;
x[i, ] = band( i-1, pot ) > 0;
end;
return( x );
finish;
a = FullFactorial( 4 );
print a [colname={A B C D}];
quit;
Thanks
I am trying to figure out the number of combinations of factors in factorial design
The number of combinations, as your code states, is 2**m.
After this, I am confused, as you have solved the problem. Could you please explain further?
I need to put them in a matrix form so I can use it in further calculations.
I need to combine my code so it depends on the number of factors. I.e if I have 3 factors it will calculate the number of combination swhich is 2**3 = 8 and output the matrix of 0's and 1's as well!!
You mention a matrix of zeros and ones, but your initial example used combinations of letters. What do you want the matrix to look like? For n=2, do you want the character matrix
"1"
"A"
"B"
"A B"
or do you want the numerical matrix
{0 0,
0 1,
1 0,
1 1};
I want the numerical matrix as it is easier for me to use it later on with the rest of the calculations in my program.
btw the numerical matrix should be:
{0 0,
1 0,
0 1,
1 1};
If the order of the rows of the matrix is not important then the problem is equivalent to counting in binary. For example
proc iml;
start FullFactorial( n );
r = 2 ## n;
x = j(r, n);
pot = 2 ## ( (n-1):0 );
do i = 1 to r;
x[i, ] = band( i-1, pot ) > 0;
end;
return( x );
finish;
a = FullFactorial( 4 );
print a [colname={A B C D}];
quit;
I am really sorry I have been using SAS for a short period. Can you please explain the code a little bit.
Do you think it can be changed to appear in the opposite order ?
Thanks,
DJ
Like this?
proc iml;
start FullFactorial( n );
r = 2 ## n;
x = j(r, n);
pot = 2 ## ( 0:(n-1) ); /* reversed powers of 2 in this line */
do i = 1 to r;
x[i, ] = band( i-1, pot ) > 0;
end;
return( x );
finish;
a = FullFactorial( 4 );
print a [colname={A B C D}];
quit;
Yes now its in the order I wanted. Sorry again I didn't understand the job of every step in this code because I am fairly new to SAS.
I appreciate your help,
DJ
Probably the simplest way is to use the EXPANDGRID function. You might need to sort the rows if the order is not in the order you want:
proc iml;
/* example for n=3 */
m = expandgrid(0:1, 0:1, 0:1);
print m;
/* if you want, you can sort: */
call sort(m, ncol(m):1);
print m;
/* n=5 columns */
m = expandgrid(0:1, 0:1, 0:1, 0:1, 0:1);
call sort(m, ncol(m):1);
print m;
Is it possible to put this within a do loop?
In my case I have different data sets with different number of factors and I need the program to work for all of them.
The number of factors are calculated using a do loop, I want to put the "expandgrid" function within the loop so it prints the matrix of 0's and 1's depending on the number of factors. Is it possible?
@DJ20 wrote:
Is it possible to put this within a do loop?
In my case I have different data sets with different number of factors and I need the program to work for all of them.
The number of factors are calculated using a do loop, I want to put the "expandgrid" function within the loop so it prints the matrix of 0's and 1's depending on the number of factors. Is it possible?
Yes, you can put any IML code into a DO loop. I am wondering if you really want a DO loop, or do you want to pass a parameter (the number of factors, let's say for example you have 5 in a particular data set) to some algorithm that then creates the matrix for 5 factors. You wouldn't want a DO loop that creates a matrix for 3 factors and then 4 factors and then 5 factors and so on ... you just want the matrix for 5 factors.
Please consider using PROC FACTEX to create the desired matrix. SAS has already done the work of programming it and debugging it and testing it, so you don't have to write your own code with DO loops and then debug it and test it.
Yes, it is possible to generate the matrix for n factors. You can create a function that builds up the function call as a string and then uses CALL EXECUTE to generate the matrix:
proc iml;
start AllZeroOneComb(n);
if n=1 then return ( {0,1} );
cmd = "m = expandgrid(";
do i = 1 to n-1;
cmd = cmd + "0:1, ";
end;
cmd = cmd + "0:1);";
*print cmd;
CALL EXECUTE(cmd);
return (m);
finish;
do n = 1 to 3;
m = AllZeroOneComb(n);
print m;
end;
You could also put Ian's algorithm into a function. Or any of the algorithms in the article, "Creating a matrix with all combinations of zeros and ones."
You can also pre-compute the matrices and stick them in a list. Then you don't need to recompute them for every data set.
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 to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.