How can I remove the diagonal elements (diagL) from my matrix L using R? I tried using the following:
subset(L, select=-diag(L)) or
subset(L, select=-c(diag(L)))
but I get 0 numbers...
How can I remove the diagonal elements (diagL) from my matrix L using R? I tried using the following:
subset(L, select=-diag(L)) or
subset(L, select=-c(diag(L)))
but I get 0 numbers...
The R programming language? I like C better, it is easier to spell.
One way is to create a matrix with the numbers the way I like them to look:
a<-t(matrix(1:16,nrow=4,ncol=4))
which looks like:
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
Delete the values on the diagonal:
diag(a)=NA
which results in:
[,1] [,2] [,3] [,4]
[1,] NA 2 3 4
[2,] 5 NA 7 8
[3,] 9 10 NA 12
[4,] 13 14 15 NA
To actually REMOVE the values, rather than just making them go away, we need to recast:
a<-t(matrix(t(a)[which(!is.na(a))],nrow=3,ncol=4))
Which results in:
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 5 7 8
[3,] 9 10 12
[4,] 13 14 15
which is the same thing as we got in C, above.
This is a little circuitous but it results in what I see as a correct answer. I would be interested in seeing an improved solution by somebody that knows R better than I do.
A bit of an explanation on the assignment:
a<-t(matrix(t(a)[which(!is.na(a))],nrow=3,ncol=4))
!is.na(a)
gives us a list of TRUE, FALSE values for which elements were nulled out.which(!is.na(a))
gives us a list of subscripts for each of the true elements.t(a)
transposes the matrix since we need to pull based upon the subscripts in #2.t(a)[which(!is.na(a))]
gives us a list of numbers that is missing the diagonal NA values.matrix(t(a)[which(!is.na(a))],nrow=3,ncol=4)
converts the list from #4 into a matrix, which is the transpose of what we want.a<-t(matrix(1:16,nrow=4,ncol=4))
(the whole thing) transposes #5 into the form we want and assigns it to the a
variable.This works with cases such as a<-t(matrix(11:26,nrow=4,ncol=4))
.
Here is some artificial data for illustration:
x <- matrix(1:16, 4, 4)
n <- nrow(x)
x
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
After vectorizing the matrix x
, the diagonal elements correspond to the indices 1, n+2, 2*n+3, ...
, that is, to the sequence seq(1, n^2, n+1)
. You can remove these indices by
x[-seq(1,n^2,n+1)]
[1] 2 3 4 5 7 8 9 10 12 13 14 15
After "removing the diagonal" of the matrix, you can either shift the lower triangular matrix upward to get a matrix with n-1
rows and n
columns by
matrix(x[-seq(1,n^2,n+1)], n-1, n)
[,1] [,2] [,3] [,4]
[1,] 2 5 9 13
[2,] 3 7 10 14
[3,] 4 8 12 15
or, and this is probably what you want, you can shift the lower triangular matrix to the right to get a matrix with n
rows and n-1
columns by transposing x
before removing the diagonal indices and transposing it back afterwards
t(matrix(t(x)[-seq(1,n^2,n+1)], n-1, n))
[,1] [,2] [,3]
[1,] 5 9 13
[2,] 2 10 14
[3,] 3 7 15
[4,] 4 8 12
Keep in mind that the diagonal is going to have the same X and Y index. A quick program to zero out the diagonal in C follows:
#include <stdio.h>
static void printMat(char mat[4][4], char *comment)
{
printf("%s:\n", comment);
for(int jj=0; jj<4; jj++) {
for(int ii=0; ii<4; ii++) {
printf("%2d ",mat[jj][ii]);
}
printf("\n");
}
}
main()
{
static char matrix[4][4]= {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9,10,11,12},
{13,14,15,16}
};
printMat(matrix,"Before");
for(int ii=0; ii<4; ii++) {
matrix[ii][ii]=0;
}
printMat(matrix,"After");
}
This results in:
Before:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
After:
0 2 3 4
5 0 7 8
9 10 0 12
13 14 15 0
To REMOVE rather that just clear the diagonal is more complicated.
This should do the trick: (Keep in mind that a memcpy of zero bytes can address elements that are not there.)
#include <stdio.h>
#include <strings.h>
static void printMat(char *mat, int xDim, int yDim,char *comment)
{
printf("%s:\n", comment);
for(int jj=0; jj<yDim; jj++) {
for(int ii=0; ii<xDim; ii++) {
printf("%2d ",(mat[(jj)*xDim+ii]) );
}
printf("\n");
}
}
main()
{
static char matrix[4][4]= {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9,10,11,12},
{13,14,15,16}
};
static char new[4][3];
printMat((char*)matrix,4,4,"Before");
for(int ii=0; ii<4; ii++) {
memcpy(&new[ii][0], &matrix[ii][0],ii);
memcpy(&new[ii][ii],&matrix[ii][ii+1], 4-ii);
}
printMat((char*)new,3,4,"After");
}
Results in:
Before:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
After:
2 3 4
5 7 8
9 10 12
13 14 15
Of course, if you want something in another language, it helps to ask.