DEV Community

Eric Gitonga
Eric Gitonga

Posted on • Updated on

Excluding Diagonal Elements from a Matrix in R

The Book of R and a 10x10 Identity Matrix

I am going through The Book of R by Tilman M. Davies as an introduction into things Data Science. During one of the exercises (4.1 part e on page 64), I came across this problem:

By extracting the diagonal elements of the logical matrix created in (c), use any to confirm there are no TRUE entries.

The said matrix is a 10×10 identity matrix. How does one do that extraction and testing? I tried everything that had been taught from the book thus far and could not find a way to do it. Off to Google I went in search of a solution.

From various sources, I got to learn of the lower.tri() and upper.tri() functions. Those seemed like they could do what I wanted. Only hitch is, I can only extract either the lower or upper half depending on the function used.

However, I have learned that you can use the c() function to combine different items into one vector. That means I can use the two functions to extract the portions I need, then combine the results, then do the required test.

For simplicity, I shall use a 3×3 identity matrix to demonstrate. First, let us form it using the diag() function and assign it to the variable t.

Command to create the 3x3 identity matrix

Next we use each of the lower.tri() and upper.tri() functions to identify the lower and upper halves of t.

Isolating the lower and upper halves.

In the arguments of both functions, we set diag = FALSE since we want to make sure the diagonals are left out. If we did not have that argument set, we would capture the ones in the diagonal, contrary to our goal.

Now we can extract each of those halves of zeros from t.

Extracting the zeros from the matrix.

Since we want to store these as FALSE, we test to see if they are equal to TRUE.

Testing if equal to TRUE to get FALSE vallues.

Now we can use the c() function to combine these two halves into one vector s.

Combining the values into one vector.

Finally, we can carry out the operation requested in the exercise.

Using any() to test for presence of TRUE values.

This confirms that extracting the diagonals of an identity matrix will result in there being no logical TRUE values left in the matrix.

There is probably a simpler way to do this. I also have a niggling thought that there is a way to extract the diagonal ones and leave the zeros in the matrix, then test the matrix using any(), but I have yet to find out how. This is one of those beginner solutions that a certain period from now will be proof of how much my knowledge of things R will have grown. If you are aware of how to do this in a simpler, more straight forward way, please do share in the comments.

Edit: And yes, there is a simpler way! I just needed to be patient and read on a few more pages of the book to page 69 which introduces the function which. Using it saves so much typing!

Much typing saved by using which()

Basically, the command selects elements in the vector that are to be extracted based on a test given. To extract some and leave others, you append a hyphen to which resulting in anything that passes the test being deleted.

My original question still remains though. Is there a way to extract the unwanted elements and still remain with a matrix? A possible solution would probably be to replace the ones with zeros then just test the matrix as a whole. Again, a little patience and reading on and paying attention (as this solution came after reading page 68) is all I needed. That led me the following:

Using the == relational operator on the matrix.

Here I used the == relational operator to identify and replace the ones in the matrix with zeros. The subsequent steps are as before; convert the zeros to FALSE then run the matrix through any(), giving us the answer expected.

This is all very exciting. There is lots to learn and discover about programming with R, and data science by extension!

Resources:

The Book of R: https://nostarch.com/bookofr

Top comments (2)

Collapse
 
skvrnami profile image
Michael Škvrňák

the diag function extracts, replaces diagonal of a matrix or creates a diagonal matrix so why don't you just use something like: any(diag(t))?

Collapse
 
egimba profile image
Eric Gitonga

Thank you for that. I am just starting out learning, so I don't know much about it, thus my journey. I shall definitely explore that.