Solved
Contributor
Posts: 20

# Matrix diagonal operation

Hi Guys,

I’m in process of converting an excel report into sas proc iml code.

I have to achieve the below, can anyone give me a hand please?

• For all diagonal values I want to get 1.
• For non-diagonal values, divide the respective values by column total. If division ends in error populate value 0.

Attached in the sample data set.

Accepted Solutions
Highlighted
Solution
‎02-15-2018 05:39 AM
Regular Contributor
Posts: 168

## Re: Matrix diagonal operation

[ Edited ]

I think this will do what you want:

``````proc iml;

x = {1 . 3, 4 5 6, -5 4 1};
n = nrow(x);
y = x / x[+, ];        /* divide by zero warnings in log */
y[do(1,n#n,n+1)] = 1;  /* set diagonal to 1 */
idx = loc(y=.);        /* find any missing values and replace with zero */
if ncol(idx)>0 then y[idx] = 0;

print x, y;
quit;``````

I have set up the first column of x to have a sum of zero, this generates missing values in the first column of y which are then replaced with zero.

All Replies
Highlighted
Solution
‎02-15-2018 05:39 AM
Regular Contributor
Posts: 168

## Re: Matrix diagonal operation

[ Edited ]

I think this will do what you want:

``````proc iml;

x = {1 . 3, 4 5 6, -5 4 1};
n = nrow(x);
y = x / x[+, ];        /* divide by zero warnings in log */
y[do(1,n#n,n+1)] = 1;  /* set diagonal to 1 */
idx = loc(y=.);        /* find any missing values and replace with zero */
if ncol(idx)>0 then y[idx] = 0;

print x, y;
quit;``````

I have set up the first column of x to have a sum of zero, this generates missing values in the first column of y which are then replaced with zero.

Contributor
Posts: 20

## Re: Matrix diagonal operation

Hi Ian,

A quick question. I want to check a condition .i.e. if the value is not zero then set the diagonal to 1.

I tried a lot but couldn't find what needs to be done to the below. Any help will really be appreciated.

Cheers

``  y[do(1,n#n,n+1)] = 1;  /* set diagonal to 1 */``

Regular Contributor
Posts: 168

## Re: Matrix diagonal operation

I think the following is what you need:

``y[do(1,n#n,n+1)] = vecdiag(y)^=.;``

which sets the diagonal to 1 wherever it is non-missing after the division, otherwise it is set to zero.

Contributor
Posts: 20

## Re: Matrix diagonal operation

Excellent. Great stuff.

Contributor
Posts: 20

## Re: Matrix diagonal operation

Hi Ian,

Trust you well. Just wondering if you can help with the below:

Now instead of 1 on the diagonal, i want 1- a matrix element.

For example:

``y[do(1,n#n,n+1)] = 1- AR; (where AR is a matrix, of same shape)``
``y[do(1,n#n,n+1)] = (1- AR); Both doesn't work. I get a error - "Matrix do not conform to the operation"Any idea?``
`` ``
Regular Contributor
Posts: 168

## Re: Matrix diagonal operation

The left hand side is referring only to the diagonal elements, while the right hand side contains n^2 elements this is the reason for the non-conforming error message.  The solution is to extract only the diagonal element of AR using the vecdiag function.

``y[do(1,n#n,n+1)] = 1 - vecdiag(AR);``
Contributor
Posts: 20

## Re: Matrix diagonal operation

Thanks a Ton Ian. You are a genius!

Cheers

☑ This topic is solved.