I would like to do symbolic matrix operations with Ryacas using a function that converts base R matrices to Ryacas format. The result of the function seems to match Ryacas format. But when I attempt to multiply the matrices, the error
# Error in aa %*% aa : requires numeric/complex matrix/vector arguments
throws. The code below is a minimal example that shows the case.
Any suggestion, please?
library(Ryacas)
conv.mat <- function(x) {
conv <- lapply(1:nrow(x), function(i) paste0(x[i, ], collapse = ", "))
conv <- paste0("List(", paste0("List(", unlist(conv), ")", collapse = ", "), ")")
noquote(conv)
}
# Writing a matrix manually for Ryacas format
a <- List(List(1, 2), List(3, 7))
a * a
# expression(list(list(7, 16), list(24, 55)))
# Writing a matrix in R and convert it to Ryacas format by the function conv.mat
aa <- matrix(c(1, 2, 3, 7), 2, byrow = TRUE)
aa <- conv.mat(aa)
# [1] List(List(1, 2), List(3, 7))
aa * aa
# Error in aa * aa : non-numeric argument to binary operator
Firstly, to multiply Ryacas matrices you want aa * aa rather than aa %*% aa. But that alone doesn't help in your case as conv.mat doesn't give exactly what we need (an expression).
We may use, e.g.,
conv.mat <- function(x)
do.call(List, lapply(1:nrow(x), function(r) do.call(List, as.list(x[r, ]))))
Then
M <- matrix(c(1, 2, 3, 7), 2, byrow = TRUE)
M %*% M
# [,1] [,2]
# [1,] 7 16
# [2,] 24 55
M <- conv.mat(M)
M * M
# expression(list(list(7, 16), list(24, 55)))
Related
I am starting to learn R and trying to multiply a 5X3 matrix with a 3X1 column vector in R; However while creating a new variable to perform the operation, R throws the error "non-conformable arrays". Can someone please point out my mistake in the code below -
*#5X3 Matrix*
X <- matrix(c(1,25.5,1.23,1,40.8,1.89,1,30.2,1.55,1,4.3,1.18,1,10.7,1.68),nrow=5,ncol=3,byrow=TRUE)
*3X1 Column vector*
b1 <- matrix(c(23,0.1,-8), nrow = 3, ncol = 1, byrow = TRUE)
v1 <- X * b1
v1
Appreciate your help :)
You need the matrix-multiplication operator %*%:
X <- matrix(c(1,25.5,1.23,1,40.8,1.89,1,30.2,1.55,1,4.3,1.18,1,10.7,1.68),nrow=5,ncol=3,byrow=TRUE)
b1 <- matrix(c(23,0.1,-8), nrow = 3, ncol = 1, byrow = TRUE)
v1 <- X %*% b1
v1
#> [,1]
#> [1,] 15.71
#> [2,] 11.96
#> [3,] 13.62
#> [4,] 13.99
#> [5,] 10.63
Normally one would use the first alternative below but the others are possible too. The first four alternatives below give a column vector as the result while the others give a plain vector without dimensions. The first three work even if b1 has more than one column. The remainder assume b1 has one column but could be generalized.
X %*% b1
crossprod(t(X), b1)
library(einsum)
einsum("ij,jk -> ik", X, b1)
out <- matrix(0, nrow(X), ncol(b1))
for(i in 1:nrow(X)) {
for(k in 1:ncol(X)) out[i] <- out[i] + X[i, k] * b1[k, 1]
}
out
colSums(t(X) * c(b1))
apply(X, 1, crossprod, b1)
sapply(1:nrow(X), function(i) sum(X[i, ] * b1))
rowSums(mapply(`*`, as.data.frame(X), b1))
rowSums(sapply(1:ncol(X), function(j) X[, j] * b1[j]))
X[, 1] * b1[1, 1] + X[, 2] * b1[2, 1] + X[, 3] * b1[3, 1]
Note
The input shown in the question is:
X <- matrix(c(1,25.5,1.23,1,40.8,1.89,1,30.2,1.55,1,4.3,1.18,1,10.7,1.68),nrow=5,ncol=3,byrow=TRUE)
b1 <- matrix(c(23,0.1,-8), nrow = 3, ncol = 1, byrow = TRUE)
How could you create a function that multiplies two matrices together? I know there is a function in R that does this already, but I want to write a function that can compute this without using the function already built in R.
It should work with sapply
res <- sapply(seq_len(ncol(matrix1)), function(i) sapply(seq_len(nrow(matrix2)),
function(j) sum(matrix1[i,] * matrix2[,j])))
Then take a transpose of the resultant
res_final <- t(res)
Not sure why you would like to do this as any "user-defined" implementation is bound to be slower than the built-in R function (and you can in fact write your own C++ implementation using Rcpp) but here is a version
matmul <- function(A, B) {
r_A <- dim(A)[1]
c_A <- dim(A)[2]
r_B <- dim(B)[1]
c_B <- dim(B)[2]
# A and B are matrices with fitting dimensions
if (c_A != r_B) {
stop("Matrix dimensions not consistent")
}
product <- matrix(nrow = r_A, ncol = c_B)
for (i in seq_len(r_A)) {
for (j in seq_len(c_B)) {
product[i,j] <- sum(A[i,] * B[,j])
}
}
return(product)
}
X <- matrix(1:12, nrow = 4, ncol = 3)
Y <- matrix(1:12, nrow = 3, ncol = 4)
print(identical(matmul(X, Y), X %*% Y))
X <- matrix(1:12, nrow = 4, ncol = 3)
Y <- matrix(1:12, nrow = 4, ncol = 3)
print(identical(matmul(X, Y), X %*% Y))
X <- matrix(1.1:12.1, nrow = 4, ncol = 3)
Y <- matrix(1:12, nrow = 3, ncol = 4)
print(identical(matmul(X, Y), X %*% Y))
Given matrices A and B, for the matrix product M = A*B, you can used the following code:
M <- t(apply(A,1,function(x) apply(B,2,function(y) sum(x*y))))
where nested apply() function is the approach here.
Example
A <- matrix(1:9,ncol = 3)
B <- matrix(1:12,nrow = 3)
M <- t(apply(A, 1, function(x) apply(B,2,function(y) sum(x*y))))
and you will get
> M
[,1] [,2] [,3] [,4]
[1,] 30 66 102 138
[2,] 36 81 126 171
[3,] 42 96 150 204
To verify the result, you can compare it with A%*%B, and it's shown the same result with the self-written code:
> A%*%B
[,1] [,2] [,3] [,4]
[1,] 30 66 102 138
[2,] 36 81 126 171
[3,] 42 96 150 204
I have a dataset with very large matrices and vectors. I would like to multiply a matrix with a vector that has one "1" element with the rest being zero. I would like to loop this calculation so that every possible 1 and 0 combination within the vector has been multiplied with the matrix, and the store the results in a vector.
I give an example of what I'm trying to do.
I have two matrices, a and b:
a <- matrix(1:16, nrow = 4, byrow = TRUE)
b <- matrix(17:32, nrow = 4, byrow = TRUE)
and a vector with 1's and 0's. As I don't know how to loop well yet, I write down the code for each combination:
c1 <- rep(0, times = 4)
c1[1] <- 1
c2 <- rep(0, times = 4)
c2[2] <- 1
c3 <- rep(0, times = 4)
c3[3] <- 1
c4 <- rep(0, times = 4)
c4[4] <- 1
I multiply a with each of the vector combinations c, diagonalize it, multiply this with b and sum each row and column. I then store this result in a vector results:
d1 <- sum(colSums(b %*% diag(as.vector(a %*% c1), nrow = 4)))
d2 <- sum(colSums(b %*% diag(as.vector(a %*% c2), nrow = 4)))
d3 <- sum(colSums(b %*% diag(as.vector(a %*% c3), nrow = 4)))
d4 <- sum(colSums(b %*% diag(as.vector(a %*% c4), nrow = 4)))
results <- cbind(d1, d2, d3, d4)
that gives:
d1 d2 d3 d4
[1,] 2824 3216 3608 4000
Is there a good line of code that does this more efficiently than what I did here?
Because of the special structure of your calculation you can shorten it to
a <- matrix(1:16, nrow = 4, byrow = TRUE)
b <- matrix(17:32, nrow = 4, byrow = TRUE)
results <- apply(a, 2, function(ai) sum(b %*% ai))
# [1] 2824 3216 3608 4000
or even shorter
colSums(b %*% a)
# [1] 2824 3216 3608 4000
I typically use Rsolnp for optimization but I am having trouble figuring out how to ask R to find values to fill a matrix (instead of a vector). Is that possible with Rsolnp or any other optimizer?
Here is a simplified example that is not working:
library(Rsolnp)
a<-matrix(rnorm(9), ncol=3)
b<-matrix(rnorm(9), ncol=3)
f1<-function(H) {
return(sum(H*a))
}
f2<-function(H) {
return(sum(H*b))
}
lH<-matrix(rep(0, 9), ncol=3)
uH<-matrix(rep(1, 9), ncol=3)
pars<-uH
target<-1.2
sol <- gosolnp(pars, fixed=NULL, fun=f1, eqfun=f2, eqB=target, LB=lH, UB=uH, distr=uH, n.restarts=10, n.sim=20000, cluster= NULL)
As you can see from the output, Rsolnp seems to be confused by the request:
> sol
$values
[1] 1e+10
$convergence
[1] 0
$pars
[1] NA NA NA NA NA NA NA NA NA
$start.pars
[1] 0.90042133 0.33262541 0.94586530 0.02083822 0.99953060 0.10720068 0.14302770 0.67162637 0.25463806
$rseed
[1] 1487866229
It seems that gosolnp() does not work with matrices. I went through the function in debugging mode and there is a call of solnp() that fails with the message:
Error in pb/cbind(vscale[(neq + 2):(neq + mm + 1)], vscale[(neq + 2):(neq + :
non-conformable arrays
But since a matrix is just a vector with the dimension attribute set, you can always reformulate your problem in terms of vectors. In your case, this is very easy, because you never do something that actually requires a matrix (like, for instance, a matrix product). Just omitting matrix() everywhere works fine.
But I assume that this is just a property of your simplified problem and your actual problem indeed needs to be expressed in terms of matrices. You could get around the problem by converting your vectors into matrices only inside the functions f1() and f2() as follows:
f1 <- function(H) {
return(sum(matrix(H, ncol = 3) * a))
}
f2 <- function(H) {
return(sum(matrix(H, ncol = 3) * b))
}
You can then define a and b as matrices as before, but lH and uH must be vectors:
a <- matrix(rnorm(9), ncol=3)
b <- matrix(rnorm(9), ncol=3)
lH <- rep(0, 9)
uH <- rep(1, 9)
pars <- uH
target <- 1.2
And now you can call gosolnp():
sol <- gosolnp(pars, fixed = NULL, fun = f1, eqfun = f2,
eqB = target, LB = lH, UB = uH, distr = uH,
n.restarts = 10, n.sim = 20000, cluster = NULL)
sol$pars
## [1] 3.917819e-08 9.999997e-01 4.748336e-07 1.000000e+00 5.255060e-09 5.114680e-10
## [7] 4.899963e-01 1.000000e+00 9.260947e-08
I have 2 matrices.
The first one:
[1,2,3]
and the second one:
[3,1,2
2,1,3
3,2,1]
I'm looking for a way to multiply them.
The result is supposed to be: [11, 13, 10]
In R, mat1%*%mat2 don't work.
You need the transpose of the second matrix to get the result you wanted:
> v1 <- c(1,2,3)
> v2 <- matrix(c(3,1,2,2,1,3,3,2,1), ncol = 3, byrow = TRUE)
> v1 %*% t(v2)
[,1] [,2] [,3]
[1,] 11 13 10
Or potentially quicker (see ?crossprod) if the real problem is larger:
> tcrossprod(v1, v2)
[,1] [,2] [,3]
[1,] 11 13 10
mat1%%mat2 Actuall y works , this gives [ 16 9 11 ]
but you want mat1 %% t(mat2). This means transpose of second matrix, then u can get [11 13 10 ]
Rcode:
mat1 = matrix(c(1,2,3),nrow=1,ncol=3,byrow=TRUE)
mat2 = matrix(c(3,1,2,2,1,3,3,2,1), nrow=3,ncol=3,byrow=TRUE)
print(mat1)
print(mat2 )
#matrix Multiplication
print(mat1 %*% mat2 )
# matrix multiply with second matrix with transpose
# Note of using function t()
print(mat1 %*% t(mat2 ))
It's difficult to say what the best answer here is because the notation in the question isn't in R, it's in matlab. It's hard to tell if the questioner wants to multiple a vector, 1 row matrix, or 1 column matrix given the mixed notation.
An alternate answer to this question is simply switch the order of the multiplication.
v1 <- c(1,2,3)
v2 <- matrix(c(3,1,2,2,1,3,3,2,1), ncol = 3, byrow = TRUE)
v2 %*% v1
This yields an answer that's a single column rather than a single row matrix.
try this one
x<-c()
y<-c()
for(i in 1:9)
{
x[i]<-as.integer(readline("Enter number for 1st matrix"))
}
for(i in 1:9)
{
y[i]<-as.integer(readline("Enter number for 2nd matrix"))
}
M1 <- matrix(x, nrow=3,ncol = 3, byrow=TRUE)
M2 <- matrix(y, nrow=3,ncol = 3, byrow=TRUE)
print(M1%*%M2)