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

Rick, an interesting idea to pre-compute the matrices and use a list.   I have come up with a recursive direct product algorithm that is well suited to this.

 

proc iml;

n = 5;
L = ListCreate( n );
L$1 = {0, 1};
do i = 1 to n - 1;
  L$(i+1) = ( L$1 @ j(2##i, 1) ) || ( {1,1} @ L$i );
end;

do i = 1 to n;
  print (L$i);
end;

The code uses the list syntax that came in with SAS/IML 14.3.

Rick_SAS
SAS Super FREQ

Very clever, Ian. I like it. As I have said in the past, you are the master of the Kronecker product. 

 

For those who (like) me, need to deconstruct Ian's magic, here is an alternative computation if the inner loop, which might be more enlightening. You can also print A and B at each iteration.

do i = 1 to n - 1;
  A = {0,1} @ j(2##i, 1);
  B = {1,1} @ L$i;
  L$(i+1) = A || B;
end;

And for those who have not used lists in SAS/IML, see the article "Create lists by using a natural syntax in SAS/IML" or watch this video on the list syntax

 

For a discussion and example of storing matrices in a list, see "Store pre-computed matrices in a list".

DJ20
Obsidian | Level 7

I tried to run your code but its giving the following error messages:

 

 

 

746 proc iml;
NOTE: IML Ready
747
748 n = 5;
749 L = ListCreate(n);
ERROR: Invocation of unresolved module LISTCREATE.

statement : ASSIGN at line 749 column 1
750 L$1 = {0, 1};
-
180
ERROR 180-322: Statement is not valid or it is used out of proper order.

751 do i = 1 to n - 1;
752 L$(i+1) = ( L$1 @ j(2**i, 1) ) || ( {1,1} @ L$i );
-
180
ERROR 180-322: Statement is not valid or it is used out of proper order.

753 end;
ERROR: END does not occur within DO group at line=753 col=1.
754
755 do i = 1 to n;
756 print (L$i);
-
22
76
ERROR 22-322: Syntax error, expecting one of the following: #, ##, &, (, (|, ), *, **, +, -, /,
//, :, <, <=, <>, =, >, ><, >=, @, [, ^=, `, |, ||.

ERROR 76-322: Syntax error, statement will be ignored.

757 end;
ERROR: END does not occur within DO group at line=757 col=1

Rick_SAS
SAS Super FREQ

You are running an old version of SAS/IML. Don't worry about it. Ian's suggestion was tangential to the discussion and isn't required to solve the problem.

DJ20
Obsidian | Level 7

Hi Rick,

 

I just want to know if its possible to edit the following code to have the matrix as a character matrix instead of numeric.

 

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;

 

For example for n=2 I should get:

"1"

"A"

"B"

"A B"

 

Thanks,

DJ

Rick_SAS
SAS Super FREQ

Sure. Index each numerical column into the character matrix {"A" "B"}. If you can't figure it out, open a new thread.

IanWakeling
Barite | Level 11

Expandgrid can accept character arguments, so it could also be done like this.

 

proc iml;

start XAllLetterComb(n);
   if n=1 then return ( {'1','A'} );
   cmd = "m = expandgrid(";
   do i = 1 to n;
      cmd = cmd + cat("{' ','", byte(65+n-i)," '}");
	  if i < n then cmd = cmd + ",";
   end;
   cmd = cmd + ");";
   *print cmd;
   CALL EXECUTE(cmd);
   m[1]='1';
   return ( compbl ( left( reverse( rowcat( m )))));
finish;

c = XAllLetterComb(5);
print c;

To see the expandgrid syntax, then uncomment the print statement.

DJ20
Obsidian | Level 7

Thanks alot.

 

This is exactly what I wanted.

 

thanks again,

DJ

DJ20
Obsidian | Level 7

thanks for your reply. I will just use Ian's.

 

thanks,

DJ

PaigeMiller
Diamond | Level 26

@DJ20 wrote:

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!!


If you want them in a matrix, you could create a SAS data set using PROC FACTEX of your factorial design, and then read that into IML. A factorial combination with letters A B C D is less useful than a matrix of 0s and 1s that would be produced by PROC FACTEX.

 

And even if you don't have PROC FACTEX in your SAS license, a DO loop in PROC IML creating a matrix of zeros and ones would be much easier to produce and would be much more usable than a matrix containing combinations of letters ABCD.

--
Paige Miller
DJ20
Obsidian | Level 7

Unfortunately my task is to write it in SAS/IML. Otherwise I would have used the FACTEX procedure for sure.

DJ20
Obsidian | Level 7

thank you very much.

 

I am going to use for the output of the ANOVA table only. For the calculations I will be using the numerical version.

 

 

Thanks,

DJ

Rick_SAS
SAS Super FREQ

Since you are new to SAS. you might want to share what you are actually trying to accomplish (other than to create a binary matrix), we might have additional advice. For example, if you are trying to compute all possible linear regression models on a set of k regressors, there are better ways

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

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
  • 27 replies
  • 1171 views
  • 6 likes
  • 5 in conversation