Get elements over opposite diagonal in a matrix in R - r

I am trying to solve a little problem with a matrix in R. I have the next matrix in R (alfa):
alfa <- matrix(1:9,nrow=3)
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
The opposite diagonal of alfa is filled of zeros. I would like to get in a new matrix all elements over this opposite diagonal (maybe the upper triangle over this diagonal). I wish to get a new matrix like this:
[,1] [,2] [,3]
[1,] 1 4 0
[2,] 2 0 0
[3,] 0 0 0
Or like this matrix with NA:
[,1] [,2] [,3]
[1,] 1 4 0
[2,] 2 0 NA
[3,] 0 NA NA
Where the elements located down the opposite diagonal of alfa are zero or NA, as you can see. I have tried with code using row(alfa) and col(alfa) but I can't get the expected matrix, for example:
(row(alfa)+col(alfa)-1)%%ncol(alfa)!=0
And I got this result where both upper and down elements over opposite diagonal are TRUE:
[,1] [,2] [,3]
[1,] TRUE TRUE FALSE
[2,] TRUE FALSE TRUE
[3,] FALSE TRUE TRUE
But I only want the upper elements, and the rest elements should be filled with zero or NA.
Many thanks for your help.

lower.tri almost does what you want, but you need to reverse the rows.
alfa[apply(lower.tri(alfa), 1, rev)] <- NA
Here, the matrix of the lower anti-diagonal is built, and used to select into alfa (vector indexing) for replacement.
lower.tri has a diag argument, which will also select the diagonal if set to TRUE.

f <- function(mat, diag = 0, offdiag = NA){
rev_vec <- seq(ncol(mat), 1)
j <- mat[,rev_vec]
j[lower.tri(j)] <- offdiag
diag(j) <- diag
j[,rev_vec]
}
You can specify if you want the off-diagonals to be NA or 0 by changing the offdiag parameter.

Related

Calculations within a matrix with internal, references that are anchored to columns within the matrix in R

I have a matrix and I would like to perform a calculation on each number in the matrix so that I get another matrix with the same dimensions only with the results of the calculation. This should be easy except that part of the equation is dependent on which column I am accessing because I will need to have an internal reference to the number at row [3,] within that column.
The equation I would like to apply is:
output matrix value = input_matrix value at a given position + (1- (matrix value at [3,] and in the same column as the input matrix value))
For example, For (1,1) in the matrix the calculation would be 1+(1-3)
For position (1,2) in the matrix, the calculation would be 5+(1-7)
input_matrix<- matrix(1:12, nrow = 4, ncol = 3)
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
The output matrix should end up looking like this:
[,1] [,2] [,3]
[1,] -1 -1 -1
[2,] 0 0 0
[3,] 1 1 1
[4,] 2 2 2
I have tried doing something like this:
output_matrix<-apply(input_matrix,c(1,2), function(x) x+(1-(input_matrix[3,])))
but that gives me three matrices with the wrong dimensions as the output.
I am thinking that perhaps I can perhaps just modify the function in the above calculation to get this to work, or alternatively write something that iterates over each column of the matrix but I am not sure exactly how to do this in a way that gives me the output matrix that I want.
Any help would be greatly appreciated.
I think this should work for you:
apply(input_matrix, margin = 2, function(x) x + (1 - x[3]))
[,1] [,2] [,3]
[1,] -1 -1 -1
[2,] 0 0 0
[3,] 1 1 1
[4,] 2 2 2
We could also do this in a vectorized way
input_matrix + (1 - input_matrix[3,][col(input_matrix)])
# [,1] [,2] [,3]
#[1,] -1 -1 -1
#[2,] 0 0 0
#[3,] 1 1 1
#[4,] 2 2 2

Converting a vector in R into a lower triangular matrix in specific order

I have a vector where the order of the elements are important, say
x <- c(1,2,3,4)
I would like to arrange my vector into a lower triangular matrix with a specific order where each row contains the preceding element of the vector. My goal is to obtain the following matrix
lower_diag_matrix
[,1] [,2] [,3] [,4]
[1,] 4 0 0 0
[2,] 3 4 0 0
[3,] 2 3 4 0
[4,] 1 2 3 4
I know I can fill the lower triangular area using lower_diag_matrix[lower.tri(lower_diag_matrix,diag = T)]<-some_vector but I can't seem to figure out the arrangement of the vector used to fill the lower triangular area. In practice the numbers will be random, so I would need a generic way to fill the area.
Here's one way:
x <- c(2, 4, 7)
M <- matrix(0, length(x), length(x))
M[lower.tri(M, diag = TRUE)] <- rev(x)[sequence(length(x):1)]
M
# [,1] [,2] [,3]
# [1,] 7 0 0
# [2,] 4 7 0
# [3,] 2 4 7

Removing matrix elements under a certain value

I hava a matrix with dimensions below, the matrix contains calculated distances between a set of genetic variants, I would like to create a new matrix or modify the PosDiff matrix to only distances that are less than or equal to 500,000.
dim(PosDiff)
[1] 597 41099
i have tried subset(), setdiff() and get wonky results such as a matrix with 1 column and a 41099 observations
Thanks
Ok let's have a go
# Generate a random matrix with 4 rows and 3 cols
> m <- matrix(runif(12), nrow=4)
> m
# [,1] [,2] [,3]
#[1,] 0.62361346 0.7793682 0.9447203
#[2,] 0.14844661 0.7335280 0.2936238
#[3,] 0.08026447 0.8172304 0.1490721
#[4,] 0.46406955 0.1701625 0.7193786
# Then keep all the elements <= 0.5 setting all the rest to NA
> m1 <- apply(m, FUN=function(x){ifelse(x<=0.5, NA, x)}, MARGIN = c(1,2))
> m1
# [,1] [,2] [,3]
#[1,] NA NA NA
#[2,] 0.14844661 NA 0.2936238
#[3,] 0.08026447 NA 0.1490721
#[4,] 0.46406955 0.1701625 NA
If you just want only the values less than 0.5 then you can run m[which(m<=0.5)]
Maybe you just need:
ifelse(PosDiff <= 500000., PosDiff, NA)
or:
ifelse(PosDiff <= 500000., PosDiff, 0)
dependently on whether you want to have missing value or 0 instead of elements which are greater than 500000.

Preserve structure, when indexing a matrix with another matrix in R

Dear StackOverflowers,
I have an integer matrix in R and I would like to subset it so that I remove 1 specified cell in each column. So that, for instance, a 4x3 matrix becomes a 3x3 matrix. I have tried doing it by creating the second logical matrix of the same dimensions.
(subject.matrix <- matrix(1:12, nrow = 4))
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
(query.matrix <- matrix(c(T, T, F, T, T, F, T, T, T, T, T, F), nrow = 4))
[,1] [,2] [,3]
[1,] TRUE TRUE TRUE
[2,] TRUE FALSE TRUE
[3,] FALSE TRUE TRUE
[4,] TRUE TRUE FALSE
The problem is that, when I index the first matrix by the second one, it is simplified to an integer vector.
subject.matrix[query.matrix]
[1] 1 2 4 5 7 8 9 10 11
I've tried adding drop=F, but to no avail. I know, I can just wrap the resulting vector into a 3x3 matrix. So the expected outcome would be:
matrix(subject.matrix[query.matrix], nrow = 3)
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 7 10
[3,] 4 8 11
But I wonder if there's a more elegant/direct solution. I'm also not attached to using a logical matrix as the index, if that means a simpler solution. Perhaps, I could subset it with a vector of indices for the rows to be removed in each column, which in this case would translate into c(3, 2, 4).
Many thanks!
Edit based on #LyzandeR suggestion: My final goal was to take column sums of the resulting matrix. So replacing the redundant values with NA's seems to be the best way to go.
I think that the only way you can preserve the matrix structure would be to use a more general way of your question edit i.e.:
matrix(subject.matrix[query.matrix], ncol = ncol(subject.matrix))
You could even convert it into a function if you plan on using it multiple times:
subset.mat <- function(mat, index, cols=ncol(mat)) {
matrix(mat[index], ncol = cols)
}
Output:
> subset.mat(subject.matrix, query.matrix)
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 7 10
[3,] 4 8 11
Also (sorry just read your updated comment) you might consider using NAs in the matrix instead of subsetting them out, which will allow you to calculate the column sums as you say:
subject.matrix[!query.matrix] <- NA
subject.matrix
# [,1] [,2] [,3]
#[1,] 1 5 9
#[2,] 2 NA 10
#[3,] NA 7 11
#[4,] 4 8 NA
This is a little brute-forceish, but I think you'll be able to extrapolate it into something more general:
new.matrix = matrix(ncol = ncol(subject.matrix), nrow = nrow(subject.matrix) - 1)
for(i in 1:ncol(subject.matrix)){
new.matrix[,i] = subject.matrix[,i][query.matrix[,i] == TRUE]
}
new.matrix
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 7 10
[3,] 4 8 11
Essentially, I just initialized an empty matrix, and then iterated through each column of subject.matrix taking only the TRUE values for query.matrix.

Efficient creation of tridiagonal matrices

How can I create a quadratic band matrix, where I give the diagonal and the first diagonal below and above the diagonal? I am looking for a function like
tridiag(upper, lower, main)
where length(upper)==length(lower)==length(main)-1 and returns, for example,
tridiag(1:3, 2:4, 3:6)
[,1] [,2] [,3] [,4]
[1,] 3 1 0 0
[2,] 2 4 2 0
[3,] 0 3 5 3
[4,] 0 0 4 6
Is there an efficient way to do it?
This function will do what you want:
tridiag <- function(upper, lower, main){
out <- matrix(0,length(main),length(main))
diag(out) <- main
indx <- seq.int(length(upper))
out[cbind(indx+1,indx)] <- lower
out[cbind(indx,indx+1)] <- upper
return(out)
}
Note that when the index to a matrix is a 2 column matrix, each row in that index is interpreted as the row and column index for a single value in the vector being assigned.

Resources