HI;
I would like to create a matrix reflecting a full factorial design. This would have the following structure
3 factors
0 0 1
0 1 0
1 0 0
0 1 1
1 1 0
1 0 1
1 1 1
I tried using allcomb but couldn't get a matrix like the above. Thanks
If the factors all have 2 levels then the full factorial is nothing more than counting in binary. So you could use something like this:
x = j(8,3);
do i = 1 to 8;
x[i, ] = band(i-1, {4 2 1}) > 0;
end;
print x;
You can generate a full factorial matrix in PROC PLAN and then read it into IML if you need it there. SAS has done the work to generate all sorts of designs, so you don't have to. It's also simple to do via looping in a DATA step, and of course you could do similar looping in IML.
Thank you I am looking at both Proc Plan and Proc Factex, but they have some limits in terms of number of factors, It would be nice to be able to do this with loops and I have played around with the program below, but instead of outputting observations in the data step I would like to work solely in IML and generate a matrix. instead, Below is what I have so far. Thanks. I have more work to do!
data design;
do i=1 to 4;
do j=1 to 4;
output;
end;
end;
run;
proc print data=design;
run;
PROC IML;
USE design;
read all var _num_ into m [colname=varnames];
l=rowvec(m);
print (l);
run;
quit;
@Sanscrit_2prov wrote:
Thank you I am looking at both Proc Plan and Proc Factex, but they have some limits in terms of number of factors,
I am not aware of a limitation on the number of factors in PROC PLAN. There's nothing in the documentation stating a limit. Why do you say this?
but instead of outputting observations in the data step I would like to work solely in IML and generate a matrix.
Yes, looping in IML can give you a full factorial, but the idea of not using SAS data steps (or did you mean not using SAS data sets?) is one that will make your life miserable. SAS is designed around the concept of a data step, and around data sets, and unless you are determined to do everything in IML, you can't (and shouldn't) avoid using data sets and data steps.
Yes I should have clarified. I use a SAS dataset read into an IML matrix.
Thank you. Ian Wakeling solved my problem,
May I ask, why do you want to do this? Seems like its a part of a larger problem?
I am recoding a Matlab program into SAS code. So I am learning IML for the first time.
Use the function EXPANDGRID it does exactly what you want, provided you have 15 factors or less.
x = expandgrid(0:1, 0:1, 0:1);
print x;
Unfortunately I have I can have more than 15 factors as they are combinations of covariate patterns. I did see Proc Factex and will check that out also. Thank you
If the factors all have 2 levels then the full factorial is nothing more than counting in binary. So you could use something like this:
x = j(8,3);
do i = 1 to 8;
x[i, ] = band(i-1, {4 2 1}) > 0;
end;
print x;
Thank you so much. This is exactly what I needed and was unaware of the band function.
If you do not need the individual elements but only the binary bit pattern, you can save quite a bit of memory by using a character string instead of a vector of 0/1 values. For example, compare BAND versus PUTN with a BINARYw. format:
proc iml;
n = 2##20;
x = band(n, 2##(20:0)) > 0;
print x;
y = putn(n, "binary20.");
print y;
For more examples and discussion, see "Creating a matrix with all combinations of zeros and ones."
I have a question.
Your code results in one row with 21 columns and the first column is a 1
How do I get all of the rows with the different columns equal to 1?
So let's say it was 4.
0000
0001
0010
etc
If you use the 'band' method, it only really makes sense to fill the matrix one row at a time as I have shown. I think Rick's point is mainly about storage space. As Paige has pointed out, the full-factorial matrix is going to be huge when you are looking at 2^16 or higher, and if you can manage with a character matrix, it will be reduce the memory requirement by a factor of 8. I have put both methods in to general modules below, so you can experiment.
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;
start FFstr( n );
fmt = cats("binary",char(n),".");
return( putn( t( 0:(2##n - 1) ), fmt) );
finish;
a = FullFactorial( 4 );
print a;
b = FFstr( 4 );
print b;
quit;
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.