Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

🔒 This topic is **solved** and **locked**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 05-08-2020 09:02 PM
(816 views)

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

10 REPLIES 10

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

*> 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;

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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!

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

2 2

-9 -9

Z

-5 -5

2 2

-9 -9

2 2

-9 -9

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;
```

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

this is great! Thank you so much!

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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}

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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`;
```

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

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.