I am using the choleski decomposition to compute the inverse of a matrix that is positive semidefinite. However, when my matrix becomes extremely large and has zeros in it I have that my matrix is no longer (numerically from the computers point of view) positive definite. So to get around this problem I use the pivot = TRUE option in the choleski command in R. However, (as you will see below) the two return the same output but with the rows and columns or the matrix rearranged. I am trying to figure out is there a way (or transformation) to make them the same. Here is my code:
X = matrix(rnorm(9),nrow=3)
A = X%*%t(X)
inv1 = function(A){
Q = chol(A)
L = t(Q)
inverse = solve(Q)%*%solve(L)
return(inverse)
}
inv2 = function(A){
Q = chol(A,pivot=TRUE)
L = t(Q)
inverse = solve(Q)%*%solve(L)
return(inverse)
}
Which when run results in:
> inv1(A)
[,1] [,2] [,3]
[1,] 9.956119 -8.187262 -4.320911
[2,] -8.187262 7.469862 3.756087
[3,] -4.320911 3.756087 3.813175
>
> inv2(A)
[,1] [,2] [,3]
[1,] 7.469862 3.756087 -8.187262
[2,] 3.756087 3.813175 -4.320911
[3,] -8.187262 -4.320911 9.956119
Is there a way to get the two answers to match? I want inv2() to return the answer from inv1().
That is explained in ?chol: the column permutation is returned as an attribute.
inv2 <- function(A){
Q <- chol(A,pivot=TRUE)
Q <- Q[, order(attr(Q,"pivot"))]
Qi <- solve(Q)
Qi %*% t(Qi)
}
inv2(A)
solve(A) # Identical
Typically
M = matrix(rnorm(9),3)
M
[,1] [,2] [,3]
[1,] 1.2109251 -0.58668426 -0.4311855
[2,] -0.8574944 0.07003322 -0.6112794
[3,] 0.4660271 -0.47364400 -1.6554356
library(Matrix)
pm1 <- as(as.integer(c(2,3,1)), "pMatrix")
M %*% pm1
[,1] [,2] [,3]
[1,] -0.4311855 1.2109251 -0.58668426
[2,] -0.6112794 -0.8574944 0.07003322
[3,] -1.6554356 0.4660271 -0.47364400
Related
A function takes two sets of values from two vectors (alpha and beta). I need to place the values of the function output in a matrix with size alpha x beta. The function calculates power values. I appreciate your help. I need a matrix 5x5. I have attempted the following code so far:
alpha = c(0.01,0.05,0.10,0.20)
beta = c(0.50,0.60,0.70,0.80,0.90)
pwrmx <- matrix(data=NA, nrow=alpha, ncol=beta)
for (a in alpha){
for (b in beta){
pwr <- power.prop.test(n=NULL, p1=0.25, p2=0.4, sig.level = a, power = b)
print(pwr$n)
}
}
you were almost there, refer the comments:
alpha = c(0.01,0.05,0.10,0.20)
beta = c(0.50,0.60,0.70,0.80,0.90)
# nrow and ncol depends on the length of alpha and beta
pwrmx <- matrix(data=NA, nrow=length(alpha), ncol=length(beta))
# iterate over the length so that you can use it to assign back at the correct index in matrix
for (i in 1:length(alpha)){
for (j in 1:length(beta)){
# as you are interested in the number n from the power analysis
pwrmx[i,j] <- (power.prop.test(n=NULL, p1=0.25, p2=0.4, sig.level = alpha[i], power = beta[j]))$n
}
}
pwrmx
# . [,1] [,2] [,3] [,4] [,5]
#[1,] 129.38048 155.72219 186.60552 226.29474 287.6656
#[2,] 74.90845 95.24355 119.70057 151.86886 202.8095
#[3,] 52.75810 70.01993 91.18885 119.50901 165.1130
#[4,] 32.02629 45.74482 63.12283 87.00637 126.4575
No need of loops, you can create a function to perform the calculation
func <- function(x, y) power.prop.test(n=NULL, p1=0.25, p2=0.4, sig.level = x, power = y)$n
and then use outer and apply the function (func) on each combination of alpha and beta
outer(alpha, beta, Vectorize(func))
# [,1] [,2] [,3] [,4] [,5]
#[1,] 129.38048 155.72219 186.60552 226.29474 287.6656
#[2,] 74.90845 95.24355 119.70057 151.86886 202.8095
#[3,] 52.75810 70.01993 91.18885 119.50901 165.1130
#[4,] 32.02629 45.74482 63.12283 87.00637 126.4575
I want to generate a random matrix which should be symmetric.
I have tried this:
matrix(sample(0:1, 25, TRUE), 5, 5)
but it is not necessarily symmetric.
How can I do that?
Another quite interesting opportunity is based on the following mathematical fact: if A is some matrix, then A multiplied by its transpose is always symmetric.
> A <- matrix(runif(25), 5, 5)
> A %*% t(A)
[,1] [,2] [,3] [,4] [,5]
[1,] 1.727769 1.0337816 1.2195505 1.4661507 1.1041355
[2,] 1.033782 1.0037048 0.7368944 0.9073632 0.7643080
[3,] 1.219551 0.7368944 1.8383986 1.3309980 0.9867812
[4,] 1.466151 0.9073632 1.3309980 1.3845322 1.0034140
[5,] 1.104135 0.7643080 0.9867812 1.0034140 0.9376534
Try this from the Matrix package
library(Matrix)
x<-Matrix(rnorm(9),3)
x
3 x 3 Matrix of class "dgeMatrix"
[,1] [,2] [,3]
[1,] -0.9873338 0.8965887 -0.6041742
[2,] -0.3729662 -0.5882091 -0.2383262
[3,] 2.1263985 -0.3550972 0.1067264
X<-forceSymmetric(x)
X
3 x 3 Matrix of class "dsyMatrix"
[,1] [,2] [,3]
[1,] -0.9873338 0.8965887 -0.6041742
[2,] 0.8965887 -0.5882091 -0.2383262
[3,] -0.6041742 -0.2383262 0.1067264
If you don't want to use a package:
n=3
x <- matrix(rnorm(n*n), n)
ind <- lower.tri(x)
x[ind] <- t(x)[ind]
x
I like this one:
n <- 3
aux <- matrix(NA, nrow = n, ncol = n)
for(i in c(1:n)){
for(j in c(i:n)){
aux[i,j] <- sample(c(1:n), 1)
aux[j,i] <- aux[i,j]
}
}
How can i write R code finding a inverse matrix without using inbuilt function? we can use "det" function.
The following function will perform any exponentiation of a matrix. The code was taken from here (link). For an inverse, set the argument EXP=-1:
#The exp.mat function performs can calculate the pseudoinverse of a matrix (EXP=-1)
#and other exponents of matrices, such as square roots (EXP=0.5) or square root of
#its inverse (EXP=-0.5).
#The function arguments are a matrix (MAT), an exponent (EXP), and a tolerance
#level for non-zero singular values.
exp.mat<-function(MAT, EXP, tol=NULL){
MAT <- as.matrix(MAT)
matdim <- dim(MAT)
if(is.null(tol)){
tol=min(1e-7, .Machine$double.eps*max(matdim)*max(MAT))
}
if(matdim[1]>=matdim[2]){
svd1 <- svd(MAT)
keep <- which(svd1$d > tol)
res <- t(svd1$u[,keep]%*%diag(svd1$d[keep]^EXP, nrow=length(keep))%*%t(svd1$v[,keep]))
}
if(matdim[1]<matdim[2]){
svd1 <- svd(t(MAT))
keep <- which(svd1$d > tol)
res <- svd1$u[,keep]%*%diag(svd1$d[keep]^EXP, nrow=length(keep))%*%t(svd1$v[,keep])
}
return(res)
}
Also, the function solve will provide the inverse:
a <- matrix(rnorm(16), 4, 4)
exp.mat(a, -1)
# [,1] [,2] [,3] [,4]
#[1,] -0.5900474 -0.3388987 0.1144450 0.38623757
#[2,] -1.0926908 -0.8692702 0.4487108 0.11958685
#[3,] 0.5967371 0.8102801 0.2292397 -0.31654754
#[4,] 0.4634810 0.4562516 -0.7958837 -0.08637801
solve(a)
# [,1] [,2] [,3] [,4]
#[1,] -0.5900474 -0.3388987 0.1144450 0.38623757
#[2,] -1.0926908 -0.8692702 0.4487108 0.11958685
#[3,] 0.5967371 0.8102801 0.2292397 -0.31654754
#[4,] 0.4634810 0.4562516 -0.7958837 -0.08637801
How do I get actual matrix using Singular value decomposition(SVD)
efficiently in R ,
cause A=svd$u %*% svd$d %*% t(svd$v) This is not an efficient way to get matrix A
Try svd(A)$u%*%diag(svd(A)$d)%*%t(svd(A)$v).
set.seed(12345)
A <- matrix(data=runif(n=9, min=1, max=9), nrow=3)
A
[,1] [,2] [,3]
[1,] 6.767231 8.088997 3.600763
[2,] 8.006186 4.651848 5.073795
[3,] 7.087859 2.330974 6.821642
s <- svd(A)
D <- diag(s$d)
s$u %*% D %*% t(s$v)
[,1] [,2] [,3]
[1,] 6.767231 8.088997 3.600763
[2,] 8.006186 4.651848 5.073795
[3,] 7.087859 2.330974 6.821642
Improving upon the answer by #MYaseen208
(s$u) %*% (t(s$v)*s$d)
This has one less matrix multiplication (which is an O(n^3) operation).
In R I need to solve a system of linear equations (Ax=b), where b=0. By using solve() it just returns a zero vector for the answer, but I want the non-zero solutions of the system. Is there any way for it?
I think you are looking for the null space of a matrix A. Try :
library(MASS)
Null(t(A))
R > (A <- matrix(c(1,2,3,2,4,7), ncol = 3, byrow = T))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 4 7
R > Null(t(A))
[,1]
[1,] -8.944272e-01
[2,] 4.472136e-01
[3,] 7.771561e-16
R > (A <- matrix(c(1,2,3,2,4,6), ncol = 3, byrow = T))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 4 6
R > Null(t(A))
[,1] [,2]
[1,] -0.5345225 -0.8017837
[2,] 0.7745419 -0.3381871
[3,] -0.3381871 0.4927193
Be careful. There are some rounding errors.
Also, denote r as the rank of matrix A, and q as the number of columns of A. If r = q, then zero vector is the only answer. If r > q, then there is no solution. If r < q, we can use the above Null function to get null space of A, but remember they are not unique, in terms of neither magnitude nor directions.
Reference : http://stat.ethz.ch/R-manual/R-patched/library/MASS/html/Null.html