Reputation: 1426
How do you determine if a matrix has an inverse in R?
So is there in R a function that with a matrix input, will return somethin like:
"TRUE" (this matrix has inverse)/"FALSE"(it hasn't ...).
Upvotes: 13
Views: 17752
Reputation: 11
some cautions might be taken when using is.singular.matrix
function from matrixcalc
package (version 1.0.6) as mentioned in @Akki's answer.
library(gtools)
library(Matrix)
# define a compositional matrix consisting of 10 observations and 8 components
set.seed(2024)
x = rdirichlet(10, alpha = rep(1,8))
y = t(x) %*% x
> rankMatrix(y)
[1] 8
attr(,"method")
[1] "tolNorm2"
attr(,"useGrad")
[1] FALSE
attr(,"tol")
[1] 1.776357e-15
> nrow(y)
[1] 8
> is.singular.matrix(y)
[1] TRUE
The rank of y
equals to the number of rows of y
, suggesting y
is a full rank matrix. Besides, solve(y)
also gives answer. but is.singular.matrix(y)
returns value TRUE
suggests y
is a singular matrix
Upvotes: 1
Reputation: 134
You can try using is.singular.matrix
function from matrixcalc
package.
To install package:
install.packages("matrixcalc")
To load it:
library(matrixcalc)
To create a matrix:
mymatrix<-matrix(rnorm(4),2,2)
To test it:
is.singular.matrix(mymatrix)
If matrix is invertible it returns FALSE
, and if matrix is singlar/non-invertible it returns TRUE
.
Upvotes: 8
Reputation: 565
Using abs(det(M)) > threshold
as a way of determining if a matrix is invertible is a very bad idea. Here's an example: consider the class of matrices cI, where I is the identity matrix and c is a constant. If c = 0.01 and I is 10 x 10, then det(cI) = 10^-20, but (cI)^-1 most definitely exists and is simply 100I. If c is small enough, det()
will underflow and return 0 even though the matrix is invertible. If you want to use determinants to check invertibility, check instead if the modulus of the log determinant is finite using determinant()
.
Upvotes: 14
Reputation: 59335
@MAB has a good point. This uses solve(...)
to decide if the matrix is invertible.
f <- function(m) class(try(solve(m),silent=T))=="matrix"
x <- matrix(rep(1,25),nc=5) # singular
y <- matrix(1+1e-10*rnorm(25),nc=5) # very nearly singular matrix
z <- 0.001*diag(1,5) # non-singular, but very smalll determinant
f(x)
# [1] FALSE
f(y)
# [1] TRUE
f(z)
# [1] TRUE
Upvotes: 7
Reputation: 23217
In addition to the solution given by @josilber in the comments (i.e. abs(det(M)) > 1e-10
) you can also use solve(M) %*% M
for a square matrix or ginv
in the MASS package will give the generalized inverse of a matrix.
To get TRUE
or FALSE
you can simply combine any of those methods with tryCatch
and any
like this:
out <- tryCatch(solve(X) %*% X, error = function(e) e)
any(class(out) == "error")
Upvotes: 2