BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Sanscrit_2prov
Obsidian | Level 7

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

1 ACCEPTED SOLUTION

Accepted Solutions
IanWakeling
Barite | Level 11

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;

View solution in original post

20 REPLIES 20
PaigeMiller
Diamond | Level 26

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.

 

--
Paige Miller
Sanscrit_2prov
Obsidian | Level 7

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;

PaigeMiller
Diamond | Level 26

@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.

--
Paige Miller
Sanscrit_2prov
Obsidian | Level 7

Yes I should have clarified. I use a SAS dataset read into an IML matrix.

Sanscrit_2prov
Obsidian | Level 7

Thank you. Ian Wakeling solved my problem,

PeterClemmensen
Tourmaline | Level 20

May I ask, why do you want to do this? Seems like its a part of a larger problem?

Sanscrit_2prov
Obsidian | Level 7

I am recoding a Matlab program into SAS code. So I am learning IML for the first time.

IanWakeling
Barite | Level 11

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;
Sanscrit_2prov
Obsidian | Level 7

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

IanWakeling
Barite | Level 11

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;
Sanscrit_2prov
Obsidian | Level 7

Thank you so much. This is exactly what I needed and was unaware of the band function.

Rick_SAS
SAS Super FREQ

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."

Sanscrit_2prov
Obsidian | Level 7

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

 

IanWakeling
Barite | Level 11

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: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

Multiple Linear Regression in SAS

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.

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 20 replies
  • 2584 views
  • 11 likes
  • 5 in conversation