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

I am looking to generate a matrix that's based on two others (letters are column names and numbers are row numbers to visualize😞

X = {u1 h1 a1, u2 h2 a2, u3 h3 a3};  

Y = {b1 f1 r1, b2 f2 r2};

what I am trying to come up with is this: 

Z = {(b1-u1)+(f1-h1)+(r1-a1) (b2-u1)+(f2-h1)+(r2-a1)

      , (b1-u2)+(f1-h2)+(r1-a2) (b2-u2)+(f2-h2)+(r2-a2)

      , (b1-u3)+(f1-h3)+(r1-a3) (b2-u3)+(f2-h3)+(r2-a3)

      , (b1-u4)+(f1-h4)+(r1-a4) (b2-u4)+(f2-h4)+(r2-a4)}

what's the most efficient way to go about this? I can only think of do-loops for each expression within parenthesis to create submatrices and then add them together? has any one done something similar. please point me in the right direction. many thanks in advance!  

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

I assume you made a mistake and the z[1,2] element should be -5 and the Z[3,1] element should be -9.

 

It looks like you want to form the matrices

M1 = Y[1, ] - X;

M2 = Y[2,] - X;

and then sum the rows of these matrices to form the columns of Z.

For this example, you can use this one-liner, which uses the '+' subscript reduction operator to get the row sums:

 

proc iml;
X = {2 7 4, 
     3 2 1, 
     5 9 3};
Y = {1 3 4, 
     2 5 1};

Z = ((Y[1,] - X)[ ,+]) || 
    ((Y[2,] - X)[ ,+]);
print Z;

If you have an arbitrary number of rows in Y, you can loop over the rows of Y like this:

free Z;
do i = 1 to nrow(Y);
   Z = Z || (Y[i,] - X)[ ,+];
end;
print Z;

It might also be possible to get this result by using matrix operators instead of a loop. Maybe by using a strategic application of the Kronecker product? If so, @IanWakeling might have a suggestion.

 

View solution in original post

10 REPLIES 10
Rick_SAS
SAS Super FREQ

> I am looking to generate a matrix that's based on two others (letters are column names and
> numbers are row numbers to visualize

X = {u1 h1 a1, u2 h2 a2, u3 h3 a3};  

Y = {b1 f1 r1, b2, f2, r2};

 

I don't understand. Can you provide numbers for the "two other" matrices and what you expect for X and Y? I don't even know what "two other" matrices you are talking about. It looks like the matrices are u, h, a, b, f, and r.

 

Without more information, the best I can suggest is vertical concatenation:

X = u || h || a;

Y = b || f || r;

 

ilya1
Fluorite | Level 6

my apologies - I made a mistake with extra commas in the second matrix. I corrected the original post. here is what I am after in numbers

X = {2 7 4, 3 2 1, 5 9 3}

Y = {1 3 4, 2 5 1}

I am trying to have Z calculate like so:

Z = {(1-2)+(3-7)+(4-4) (2-2)+(5-7)+(4-1)

       ,(1-3)+(3-2)+(4-1) (2-3)+(5-2)+(1-1)

       ,(1-5)+(3-9)+(4-3) (2-5)+(5-9)+(1-3)} 

so result looks like this:

Z = {-5 1, 2 2, 9 -9}

 

many thanks in advance for your thoughts!

Rick_SAS
SAS Super FREQ

I assume you made a mistake and the z[1,2] element should be -5 and the Z[3,1] element should be -9.

 

It looks like you want to form the matrices

M1 = Y[1, ] - X;

M2 = Y[2,] - X;

and then sum the rows of these matrices to form the columns of Z.

For this example, you can use this one-liner, which uses the '+' subscript reduction operator to get the row sums:

 

proc iml;
X = {2 7 4, 
     3 2 1, 
     5 9 3};
Y = {1 3 4, 
     2 5 1};

Z = ((Y[1,] - X)[ ,+]) || 
    ((Y[2,] - X)[ ,+]);
print Z;

If you have an arbitrary number of rows in Y, you can loop over the rows of Y like this:

free Z;
do i = 1 to nrow(Y);
   Z = Z || (Y[i,] - X)[ ,+];
end;
print Z;

It might also be possible to get this result by using matrix operators instead of a loop. Maybe by using a strategic application of the Kronecker product? If so, @IanWakeling might have a suggestion.

 

ilya1
Fluorite | Level 6

Thank you! This is almost there! 

I just can't figure out why calculation is always on the first element of X and Y

here is Z after calculating it both ways (loop or no loop, same result)

 

                                                Z
                                                -5        -5
                                                 2         2
                                                -9        -9

                                                  Z
                                                -5        -5
                                                 2         2
                                                -9        -9
Rick_SAS
SAS Super FREQ

Because both rows of Y sum to 8. You can further simplify the computation to become 

 

rowSumX = X[ ,+];    /* sum of rows of X */
Z = Y[1 ,+] - rowSumX  ||
    Y[1 ,+] - rowSumX;
print Z;
ilya1
Fluorite | Level 6

this is great! Thank you so much!

IanWakeling
Barite | Level 11

You could apply the Kroneker product (the @ operator) and avoid the loop as follows:

diff = Y @ j(nrow(X), 1) - j(nrow(Y), 1) @ X;
Z = shapecol( diff[ ,+], nrow(X));
print Z;

It is not as easy to see what is going on, so you may prefer Rick's solution if others need to use your code.

ilya1
Fluorite | Level 6

Thank you! I need to study up this approach - not easy to see. 

I am just curious - how to make this work on multiplication?

 

a = {1 2 3}

b={1 2 3, 4 5 6, 7 8 9}

 

to get to:

c={1 4 9, 4 10 18, 7 16 27}

ilya1
Fluorite | Level 6

never mind - this is just element wise multiplication. I am thinking too much I suppose. 🙂

IanWakeling
Barite | Level 11

Indeed it is elementwise multiplication, but if you want the row sums of c, which was part of the original problem, then the whole process simplifies to normal matrix multiplication:

 

a = {1 2 3};
b = {1 2 3, 4 5 6, 7 8 9};
d = b * a`;

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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
  • 10 replies
  • 817 views
  • 4 likes
  • 3 in conversation