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

Hello,
I would like to reshape the matrix A :
   1   2   3
   4   5   6
   7   8   9
 10 11 12
 13 14 15
 16 17 18
 19 20 21
 22 23 24

which is (8*3) into the following matrix (4*6):
  1   2   3 13 14 15
  4   5   6 16 17 18
  7   8   9 19 20 21
10 11 12 22 23 24

In the following code, test2 delivers this for this simplified example, but it does not suit when the actual matrix is for example (9000*3) and has to be reshaped in (450*60), i.e each of the 20 blocks of (450*3) moves on the right, one after another. So I would prefer a code more general like test1, but the shape function - in this form at least - does not deliver the result I want.

 

proc IML;
	A = {1 2 3, 4 5 6, 7 8 9, 10 11 12, 13 14 15, 16 17 18, 19 20 21, 22 23 24};
	test1 = shape(A, 4, 6);
	test2 = A[1:4,] || A[5:8,];
quit;

Thank you for your help,

1 ACCEPTED SOLUTION

Accepted Solutions
IanWakeling
Barite | Level 11

I think this might do what you want, where all you need to do is pre-specify the number of blocks required.

 

proc iml;

x = shape(1:36,12,3);
print x;

nblocks = 3;
cidx = shape(1:ncol(x)#nblocks, ncol(x), nblocks);
y = shapecol(x, nrow(x)/nblocks)[ ,t(cidx)];
print y;
quit;

View solution in original post

6 REPLIES 6
Rick_SAS
SAS Super FREQ

If the original matrix is N x 3, it is not clear to me how you are forming the final matrix in terms of N. For example, in the 9000 x 3 example, what are the rules for getting the 450 x 60 matrix? You mention "blocks of 20", so I thought you were looking for a 20 x 1350 matrix as the output.  

 

If N is the number of rows in the original matrix and p is the number of columns (is p always 3???) and k is the "block size", can you describe how to get the new matrix from the old?

IanWakeling
Barite | Level 11

I think this might do what you want, where all you need to do is pre-specify the number of blocks required.

 

proc iml;

x = shape(1:36,12,3);
print x;

nblocks = 3;
cidx = shape(1:ncol(x)#nblocks, ncol(x), nblocks);
y = shapecol(x, nrow(x)/nblocks)[ ,t(cidx)];
print y;
quit;
Alain38
Quartz | Level 8

Perfect! Thank you very much!

Rick_SAS
SAS Super FREQ

Oh, I see now. After studying the question and Ian's solution, it appears that the OP is asking for a block transpose. You can use the BTRAN function in SAS/IML to compute a block transpose. It is not clear whether the OP wants to specify the blocksize or the number of blocks. Both options are shown below:

 

proc iml;
x = shape(1:36,12,3);
blocksize = 4;
y = btran(x, blocksize, ncol(x));
print y;

x = shape(1:9000*3,0,3);     /* 9000 x 3 matrix */
nblocks = 20;
blocksize = nrow(x) / nblocks;
y = btran(x, blocksize, ncol(x));
print (dimension(y))[c={"nrow" "ncol"}];
Alain38
Quartz | Level 8

Works well too! Thank you very much!

IanWakeling
Barite | Level 11

Oh! I did it the hard way, because I didn't know that BTRAN existed.  Perhaps you should blog about it Rick, to try and get it more widely known?

sas-innovate-white.png

Missed SAS Innovate in Orlando?

Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.

 

Register now

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 6 replies
  • 1937 views
  • 3 likes
  • 3 in conversation