Related
I have two matrices for example:
> A
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> B
[,1] [,2]
[1,] 7 10
[2,] 8 11
[3,] 9 12
and I want a vector called C whose element C[i]=A[i,]*B[,i], so the outcome should be:
> C
[,1]
[1,] 76
[2,] 136
I used the for loop for (i in 1:2) {C[i]=A[i,]%*%B[,i]}. But it is very slow.
And I also tried A%*%B and take elements in the diagonal, and it just make my computer crash when the matrix is large.
Could you please give me some suggestions? Thanks so much!
A straight multiplication (not matrix multiplication but element-wise multiplication) could work for what we want. That gets the multiplications we want - after that we just want to take the sum of the rows. If we need the result to be a column matrix we can convert to matrix.
> A <- matrix(1:6, nrow = 2)
> A
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> B <- matrix(7:12, ncol = 2)
> B
[,1] [,2]
[1,] 7 10
[2,] 8 11
[3,] 9 12
> rowSums(A * t(B))
[1] 76 136
> as.matrix(rowSums(A * t(B)))
[,1]
[1,] 76
[2,] 136
mapply(function(a,b) sum(a*b), asplit(A, 1), asplit(B, 2))
# [1] 76 136
I'm pretty new to the R language and trying to find out how you can calculate the inverse of a matrix that isn't square. (non-square? irregular? I'm unsure of the correct terminology).
From my book and a quick google search, (see source), I've found you can use solve(a) to find the inverse of a matrix if a is square.
The matrix I have created is, and from what I understand, not square:
> matX<-matrix(c(rep(1, 8),2,3,4,0,6,4,3,7,-2,-4,3,5,7,8,9,11), nrow=8, ncol=3);
> matX
[,1] [,2] [,3]
[1,] 1 2 -2
[2,] 1 3 -4
[3,] 1 4 3
[4,] 1 0 5
[5,] 1 6 7
[6,] 1 4 8
[7,] 1 3 9
[8,] 1 7 11
>
Is there a function for solving a matrix of this size or will I have to do something to each element? as the solve() function gives this error:
Error in solve.default(matX) : 'a' (8 x 3) must be square
The calculation I'm trying to achieve from the above matrix is: (matX'matX)^-1
Thanks in advance.
ginv ginv in the MASS package will give the generalized inverse of a matrix. Premultiplying the original matrix by it will give the identity:
library(MASS)
inv <- ginv(matX)
# test it out
inv %*% matX
## [,1] [,2] [,3]
## [1,] 1.000000e+00 6.661338e-16 4.440892e-15
## [2,] -8.326673e-17 1.000000e+00 -1.110223e-15
## [3,] 6.938894e-17 8.326673e-17 1.000000e+00
As suggested in the comments this can be displayed in a nicer way using zapsmall:
zapsmall(inv %*% matX)
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 1 0
## [3,] 0 0 1
The inverse of matX'matX is now:
tcrossprod(inv)
## [,1] [,2] [,3]
## [1,] 0.513763935 -0.104219636 -0.002371406
## [2,] -0.104219636 0.038700372 -0.007798748
## [3,] -0.002371406 -0.007798748 0.006625269
solve however, if you aim is to calculate the inverse of matX'matX you don't need it in the first place. This does not involve MASS:
solve(crossprod(matX))
## [,1] [,2] [,3]
## [1,] 0.513763935 -0.104219636 -0.002371406
## [2,] -0.104219636 0.038700372 -0.007798748
## [3,] -0.002371406 -0.007798748 0.006625269
svd The svd could also be used and similarly does not require MASS:
with(svd(matX), v %*% diag(1/d^2) %*% t(v))
## [,1] [,2] [,3]
## [1,] 0.513763935 -0.104219636 -0.002371406
## [2,] -0.104219636 0.038700372 -0.007798748
## [3,] -0.002371406 -0.007798748 0.006625269
ADDED some additional info.
You can do what's called a "Moore–Penrose pseudoinverse". Here's a function exp.matthat will do this for you. There is also an example outlining it's use here.
exp.mat():
#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)
}
example of use:
source("exp.mat.R")
X <- matrix(c(rep(1, 8),2,3,4,0,6,4,3,7,-2,-4,3,5,7,8,9,11), nrow=8, ncol=3)
iX <- exp.mat(X, -1)
zapsmall(iX %*% X) # results in identity matrix
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
How to solve a non-square linear system with R : A X = B ?
(in the case the system has no solution or infinitely many solutions)
Example :
A=matrix(c(0,1,-2,3,5,-3,1,-2,5,-2,-1,1),3,4,T)
B=matrix(c(-17,28,11),3,1,T)
A
[,1] [,2] [,3] [,4]
[1,] 0 1 -2 3
[2,] 5 -3 1 -2
[3,] 5 -2 -1 1
B
[,1]
[1,] -17
[2,] 28
[3,] 11
If the matrix A has more rows than columns, then you should use least squares fit.
If the matrix A has fewer rows than columns, then you should perform singular value decomposition. Each algorithm does the best it can to give you a solution by using assumptions.
Here's a link that shows how to use SVD as a solver:
http://www.ecse.rpi.edu/~qji/CV/svd_review.pdf
Let's apply it to your problem and see if it works:
Your input matrix A and known RHS vector B:
> A=matrix(c(0,1,-2,3,5,-3,1,-2,5,-2,-1,1),3,4,T)
> B=matrix(c(-17,28,11),3,1,T)
> A
[,1] [,2] [,3] [,4]
[1,] 0 1 -2 3
[2,] 5 -3 1 -2
[3,] 5 -2 -1 1
> B
[,1]
[1,] -17
[2,] 28
[3,] 11
Let's decompose your A matrix:
> asvd = svd(A)
> asvd
$d
[1] 8.007081e+00 4.459446e+00 4.022656e-16
$u
[,1] [,2] [,3]
[1,] -0.1295469 -0.8061540 0.5773503
[2,] 0.7629233 0.2908861 0.5773503
[3,] 0.6333764 -0.5152679 -0.5773503
$v
[,1] [,2] [,3]
[1,] 0.87191556 -0.2515803 -0.1764323
[2,] -0.46022634 -0.1453716 -0.4694190
[3,] 0.04853711 0.5423235 0.6394484
[4,] -0.15999723 -0.7883272 0.5827720
> adiag = diag(1/asvd$d)
> adiag
[,1] [,2] [,3]
[1,] 0.1248895 0.0000000 0.00000e+00
[2,] 0.0000000 0.2242431 0.00000e+00
[3,] 0.0000000 0.0000000 2.48592e+15
Here's the key: the third eigenvalue in d is very small; conversely, the diagonal element in adiag is very large. Before solving, set it equal to zero:
> adiag[3,3] = 0
> adiag
[,1] [,2] [,3]
[1,] 0.1248895 0.0000000 0
[2,] 0.0000000 0.2242431 0
[3,] 0.0000000 0.0000000 0
Now let's compute the solution (see slide 16 in the link I gave you above):
> solution = asvd$v %*% adiag %*% t(asvd$u) %*% B
> solution
[,1]
[1,] 2.411765
[2,] -2.282353
[3,] 2.152941
[4,] -3.470588
Now that we have a solution, let's substitute it back to see if it gives us the same B:
> check = A %*% solution
> check
[,1]
[1,] -17
[2,] 28
[3,] 11
That's the B side you started with, so I think we're good.
Here's another nice SVD discussion from AMS:
http://www.ams.org/samplings/feature-column/fcarc-svd
Aim is to solve Ax = b
where A is p by q, x is q by 1 and b is p by 1 for x given A and b.
Approach 1: Generalized Inverse: Moore-Penrose
https://en.wikipedia.org/wiki/Generalized_inverse
Multiplying both sides of the equation, we get
A'Ax = A' b
where A' is the transpose of A. Note that A'A is q by q matrix now. One way to solve this now multiply both sides of the equation by the inverse of A'A. Which gives,
x = (A'A)^{-1} A' b
This is the theory behind generalized inverse. Here G = (A'A)^{-1} A' is pseudo-inverse of A.
library(MASS)
ginv(A) %*% B
# [,1]
#[1,] 2.411765
#[2,] -2.282353
#[3,] 2.152941
#[4,] -3.470588
Approach 2: Generalized Inverse using SVD.
#duffymo used SVD to obtain a pseudoinverse of A.
However, last elements of svd(A)$d may not be quite as small as in this example. So, probably one shouldn't use that method as is. Here's an example where none of the last elements of A is close to zero.
A <- as.matrix(iris[11:13, -5])
A
# Sepal.Length Sepal.Width Petal.Length Petal.Width
# 11 5.4 3.7 1.5 0.2
# 12 4.8 3.4 1.6 0.2
# 13 4.8 3.0 1.4 0.1
svd(A)$d
# [1] 10.7820526 0.2630862 0.1677126
One option would be to look as the singular values in cor(A)
svd(cor(A))$d
# [1] 2.904194e+00 1.095806e+00 1.876146e-16 1.155796e-17
Now, it is clear there is only two large singular values are present. So, one now can apply svd on A to get pseudo-inverse as below.
svda <- svd(A)
G = svda$v[, 1:2] %*% diag(1/svda$d[1:2]) %*% t(svda$u[, 1:2])
# to get x
G %*% B
I have two Matrices, one is binary (Zero or One) and the other is an integer matrix of the same dimensions, these are square matrices.
I'd like an efficient way of combining them in a specific way, without iteration along each element.
The way I'd like to combine them is to have a resultant matrix from matrix A and matrix B, that for the element, takes the lowest number that is not zero.
Can anyone think of a trick in R to achieve this, I've tried to do it mathematically but keep coming up short, I was wondering if there was a way to overlay the matrices with a conditional statement?
matA <- matrix(-8:7, 4,4); set.seed(123)
matB <- matrix(sample(0:1, 16, repl=TRUE), 4, 4)
matC <- matrix(NA, nrow(matA), ncol(matA))
matC[] <- pmin( matA, MatB)
matC[ matB==0] <- matA[matB==0]
matB
#-----------
[,1] [,2] [,3] [,4]
[1,] 0 1 1 1
[2,] 1 0 0 1
[3,] 0 1 1 0
[4,] 1 1 0 1
matC
#---------
[,1] [,2] [,3] [,4]
[1,] -8 -4 0 1
[2,] -7 -3 1 1
[3,] -6 -2 1 6
[4,] -5 -1 3 1
flodel's method produces:
> ifelse(matB == 0, matB, pmin(matA, matB))
[,1] [,2] [,3] [,4]
[1,] 0 -4 0 1
[2,] -7 0 0 1
[3,] 0 -2 1 0
[4,] -5 -1 0 1
mnel's method produces:
> (matB * !matA) + matA
[,1] [,2] [,3] [,4]
[1,] -8 -4 1 4
[2,] -7 -3 1 5
[3,] -6 -2 2 6
[4,] -5 -1 3 7
My guess is:
ifelse(A == 0, B, pmin(A, B))
or maybe
ifelse(A == 0, B, ifelse(B == 0, A, pmin(A, B)))
If this is not what you are looking for, please clarify (and maybe provide an example.)
From #A_Skeleton's comment on scaling, you could break your matrix into chunks:
mnel <- function(matA, matB) {
(matB * !matA) + matA
}
# method takes a function as the argument
mcombine <- function(matA, matB, method) {
chunkSize <- 10000
matC <- matrix(0, nrow(matA), ncol(matA))
for (i in 1:floor(nrow(matA) / chunkSize)) {
curRange <- (chunkSize * (i-1) + 1):(i * chunkSize)
matC[curRange,] <- method(matA[curRange,], matB[curRange,])
}
# handle case where dimensions don't divide exactly into chunks
lastRange <- i*chunkSize:nrow(matA)
matC[lastRange,] <- method(matA[lastRange,], matB[lastRange,])
matC
}
# Using mnel's method:
matC <- mcombine(matA, matB, mnel)
R - how to vectorize computation of sum of outer products, when vectors are in two matrices - X and Y ?
Example :
X = cbind(1:3, 2:4)
Y = cbind(0:2, c(0,0,1))
> X
[,1] [,2]
[1,] 1 2
[2,] 2 3
[3,] 3 4
> Y
[,1] [,2]
[1,] 0 0
[2,] 1 0
[3,] 2 1
> outer(X[1,],Y[1,]) + outer(X[2,],Y[2,]) + outer(X[3,],Y[3,])
[,1] [,2]
[1,] 8 3
[2,] 11 4
I would like to vectorize operation :
outer(X[1,],Y[1,]) + outer(X[2,],Y[2,]) + outer(X[3,],Y[3,]) - is it possible ? Mayby something with general construction like : lapply( ,FUN=outer), and then taking sum of elements in list ? Otherwise I have to loop over outer(X[i,],Y[i,]).
This is just matrix multiplication:
t(X) %*% Y
v [,1] [,2]
# [1,] 8 3
# [2,] 11 4
You need a 2*2 matrix and both matrices X and Y are of dimensons 3*2. Transposing X gives 2*3 and when multiplied with 3*2 matrix gives the desired 2*2 matrix.