Statistical programming, matrix languages, and more

Matrix diagonal operation

Accepted Solution Solved
Reply
Contributor
Posts: 20
Accepted Solution

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
Solution
‎02-15-2018 05:39 AM
Regular Contributor
Posts: 168

Re: Matrix diagonal operation

[ Edited ]
Posted in reply to akpattnaik

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.

 

View solution in original post


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

Re: Matrix diagonal operation

[ Edited ]
Posted in reply to akpattnaik

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

Posted in reply to IanWakeling

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

Posted in reply to akpattnaik

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

Posted in reply to IanWakeling

Excellent. Great stuff.

Contributor
Posts: 20

Re: Matrix diagonal operation

Posted in reply to akpattnaik

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

Posted in reply to akpattnaik

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);
Highlighted
Contributor
Posts: 20

Re: Matrix diagonal operation

Posted in reply to IanWakeling

Thanks a Ton Ian. You are a genius!

 

Cheers

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 7 replies
  • 356 views
  • 1 like
  • 2 in conversation