Inconsistent vector operations in R? - r

I teach mathematics and programming (with R) at university and I am a big fan of a good and consistent notation. Please have a look at the following simple vector operations in R:
> v1 <- c(1,2,3)
> v2 <- c(4,5,6)
> v1 %*% v2
[,1]
[1,] 32
> t(v1) %*% v2
[,1]
[1,] 32
> v1 %*% t(v2)
[,1] [,2] [,3]
[1,] 4 5 6
[2,] 8 10 12
[3,] 12 15 18
> t(v1) %*% t(v2)
Error in t(v1) %*% t(v2) : non-conformable arguments
> v1 + v2
[1] 5 7 9
> v1 + t(v2)
[,1] [,2] [,3]
[1,] 5 7 9
> t(v1) + t(v2)
[,1] [,2] [,3]
[1,] 5 7 9
I think there are some inconsistencies here: Either I am missing something or R seems to be quite arbitrary with respect to what results you get when you either transpose a vector or not.
What is the underlying logic here (which seems to be completely different than Matlab by the way).

?%*% gives the logic:
Multiplies two matrices, if they are conformable. If one argument
is a vector, it will be promoted to either a row or column matrix
to make the two arguments conformable. If both are vectors it
will return the inner product (as a matrix).
If they're both vectors (first example), then you get the inner product. If you put a t( ) in there, the vector will get cast as a column matrix, and a vector is effectively a row matrix, so normable conformable rules apply.
Similarly, the help page for "+" says that it will cast the arguments to vectors - and gives some guidance on the 'shape' of the result.

Related

Matrix in R programming

learning R programming recently, here's a exercise I cannot figure it out.
This program that asks the user for the 8 values of a 2 2x2 mathematical matrix. Another words, there are 4 values in one 2x2 matrix and another 4 values for the
second matrix.
Then the program should has the user if they want to add, subtract, multiple or divided the 2 matrices. Print the record.
Please see attached for the sample output.
Sample output
I'm a biginner in R programming and I don't speak english very well, but I'll try to explain to you.
First, you can create matrices lik Amar did :
m1 <- matrix( rep(2,4) , ncol = 2) #rep(x,n) : repeat x n times
m2 <- matrix( c(2,3,5,6) , nrow = 2 , ncol = 2) #Personaly I prefer to precise the number of rows and columns
> m1
[,1] [,2]
[1,] 2 2
[2,] 2 2
> m2
[,1] [,2]
[1,] 2 5
[2,] 3 6
The operations
You can use "traditional" operations on matrices : + - * /
But you have to know that operations are applied on matrix's elements one by one
consider that m3 = m1*m2 ; that means that m3[i,j] = m1[i,j]*m2[i,j]
m3 <- m1*m2
[,1] [,2]
[1,] 4 10
[2,] 6 12
This is clearly not what is matrices multiplication in mathematics
N.B.: the classic addition (+) is correct
For matrices multiplication you have to use the operation %*%
> m4 <- m1%*%m2
> m4
[,1] [,2]
[1,] 10 22
[2,] 10 22
Fo division don't use the operation %/% because it's not division but modulus. and it returnus modulus applied to matrices elements one by one. m5 = m1%/%m2 means m5[i,j]=m1[i,j]%/%m2[i,j]
> m5 <- m1%/%m2
> m5
[,1] [,2]
[1,] 1 0
[2,] 0 0
Please note that in mathematics the division is not applied on matrices. If you have the equation m6*m2 = m1 then m6 = m1*inverse(m2)
to inverse a matrix you have to install the package matlib :
install.packages("matlib")
> m6 <- m1*inv(m2)
> m6
[,1] [,2]
[1,] -4 3.333333
[2,] 2 -1.333333
Important ! to inverse a matrix, the determinant should be different from 0 :
> det(m2)
[1] -3
> inv(m2)
[,1] [,2]
[1,] -2 1.6666667
[2,] 1 -0.6666667
> det(m1)
[1] 0
> inv(m1)
Error in Inverse(X, tol = sqrt(.Machine$double.eps), ...) :
X is numerically singular
In R, if you have a matrix:
m1 <- matrix(c(2,2,2,2), ncol = 2)
m2 <- matrix(c(4,4,4,4), ncol = 2)
and you want to add/subtract/divide/multiple the two you simply:
m1 + m2
[,1] [,2]
[1,] 6 6
[2,] 6 6
If you store the inputted values in a list, you can refer to it inside the matrix function as above:
matrix(user_input, ncol = 2)
#or
matrix(c(ui1, ui2, ui3, ui4), ncol = 2)
To ask for user-input, look at this SO answer: Creating a Prompt/Answer system to input data into R

Avoid the for loop

I would like to compute the product between the each row of a matrix x with itself. And then sum the result of all these products. The result is a scalar. I make the following coda that works but is not efficient. Can someone help me to avoid the for loop?
for(i in 1:nrow(x){
resid2[i] <- t(x[i,])%*% x[i,]
}
V = sum(resid2)/
The solution is just the sum of squares of all elements of the matrix.
V = sum(x^2)
which can also be calculated via matrix multiplication as:
V = crossprod(as.vector(x))
The intermediate vector resid2 can be calculated as
resid2 = rowSums(x^2)
V = sum(resid2)
Here is an answer that swaps the for loop out for the apply family.
sum(apply(x, margin = 1, function(z) z%*%z))
The apply function takes the matrix x, margin = 1 means for each row (as opposed to margin = 2 which means each column). So, for each row in x run a function that multiplies that row by itself: function(z) z%*%z
If I understand you correctly, you don't need to loop at all. mat %*% mat should do it:
mat <- matrix(seq.int(9), nrow=3)
mat
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
mat %*% mat
## [,1] [,2] [,3]
## [1,] 30 66 102
## [2,] 36 81 126
## [3,] 42 96 150

Strange behavior of apply/ reverse function in R

I have a simple matrix:
mat = rbind(c(1:3),c(4:6),c(7:9))
mat
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# [3,] 7 8 9
I want to now reverse the matrix row-wise. That is I want to obtain:
revMat
# [,1] [,2] [,3]
# [1,] 3 2 1
# [2,] 6 5 4
# [3,] 9 8 7
To do this I tried
apply(mat, 1, rev)
And the result was:
# [,1] [,2] [,3]
# [1,] 3 6 9
# [2,] 2 5 8
# [3,] 1 4 7
I find this to be extremely strange. It's like the rows are reversed and then the final matrix is transposed. I don't understand why. If I try simply, for instance,
apply(mat, 2, rev)
it gives me the expected reversal of each column
# [,1] [,2] [,3]
# [1,] 7 8 9
# [2,] 4 5 6
# [3,] 1 2 3
Therefore to obtain the final result I have to perform
t(apply(t(bg), 2, rev))
Thus obtaining the required matrix is NOT a problem for me, but I don't understand the "anomaly" in the behavior of apply/ reverse. Can anyone explain this to me?
Edit: To make clear the distinction, I already know how to do the reversal. I want to know WHY this happens. How to is clear from many earlier questions including
How to reverse a matrix in R?
apply always puts the result in the first dimension. See ?apply for more information. Assuming this input:
mat <- matrix(1:9, 3, byrow = TRUE)
here are some alternatives:
1) transpose
t(apply(mat, 1, rev))
2) avoid apply with indexing
mat[, 3:1]
3) iapply An idempotent apply was posted here:
https://stat.ethz.ch/pipermail/r-help/2006-January/086064.html
Using that we have:
iapply(mat, 1, rev)
There was also an idempotent apply, iapply, in version 0.8.0 of the reshape package (but not in the latest version of reshape): https://cran.r-project.org/src/contrib/Archive/reshape/
4) rollapply rollapply in the zoo package can be used:
library(zoo)
rollapply(mat, 1, rev, by.column = FALSE)
5) tapply The tapply expression here returns a list giving us the opportunity to put it together in the way we want -- in this case using rbind:
do.call("rbind", tapply(mat, row(mat), rev))
6) multiply by a reverse diagonal matrix Since rev is a linear operator it can be represented by a matrix:
mat %*% apply(diag(3), 1, rev)
or
mat %*% (row(mat) + col(mat) == 3+1)
If you look at the help for apply(), this is exactly the behavior you would expect:
Value
If each call to FUN returns a vector of length n, then apply returns
an array of dimension c(n, dim(X)[MARGIN]) if n > 1.
a nice option to do what you want is to use indexing:
mat[,ncol(mat):1]

Loop Matrix to store in Cube

I want to loop an equation through a matrix and store the results in a cube, so that Cube[,,1] is one result of the matrix.
I currently have written the following
PercentileReturn <- array(NA, c(RetAge,length(Percentile)+1,nrow(Demo)))
for (i in 1:nrow(Demo)) {
PercentileReturn[,,i] <-
PercentileReturn[Demo[i,3]:RetAge,
1:length(Percentile),1]<-
t(apply((apply(AnnualReturns[(Demo[i,3]):RetAge,],2,cumprod)) *
Demo[i,4],1,function(x){quantile(x, Percentile, na.rm=T)}))
}
and it results in the following error
Error in PercentileReturn[, , i] <- PercentileReturn[Demo[i, 3]:RetAge, :
number of items to replace is not a multiple of replacement length
I assume it's because the Matrix I am trying to plug in isn't in 3 dimensions.
Basically a stripped down version would be to have an
array(NA,c(2,2,3)) populated with a matrix times a vector
so that say
Matrix * vector c(1,2,3)
[,1] [,2]
[1,] 4 4
[2,] 4 4
would result in the following cube
, , 1
[,1] [,2]
[1,] 4 4
[2,] 4 4
, , 2
[,1] [,2]
[1,] 8 8
[2,] 8 8
, , 3
[,1] [,2]
[1,] 12 12
[2,] 12 12
That will do it:
M <- matrix(1:4,2) # in your example M <- matrix(4, 2,2)
x <- 1:3
array(sapply(x, function(xi) M*xi), c(dim(M), length(x)))
I found the error the first
PercentileReturn[,,i]
has to also match the dimensions of the loop data below written as
PercentileReturn[Demo[i,3]:RetAge,1:length(Percentile),i]
Thanks Jogo, I will be using something similar to what you wrote in another issue down the line.

Can I multiply vectors of different lengths?

v1 <- c(1,2)
v2 <- c(3,4,5,6)
Is there a way to multiply these two vectors such that the result is a vector dim(1,3)
such as (11,14,17)
This is analogous to all possible dim(1,2) multiplication combinations such as
(1,2) %x% t(3,4), (1,2) %x% t(4,5), (1,2) %x% t(5,6)
It seems so simple, have looked and no luck.
Create a 2-row matrix:
> rbind(v2[-length(v2)],v2[-1])
[,1] [,2] [,3]
[1,] 3 4 5
[2,] 4 5 6
Then it's just matrix multi:
> v1 %*% rbind(v2[-length(v2)],v2[-1])
[,1] [,2] [,3]
[1,] 11 14 17
and subset if you want a vector:
> (v1 %*% rbind(v2[-length(v2)],v2[-1]))[1,]
[1] 11 14 17
Use subsetting and cbind to create a matrix of your combinations, then apply across the rows of this with your multiplication.
apply(cbind(v2[-length(v2)],v2[-1]),1,function(x) v1%*%x)
[1] 11 14 17
Similar to James' answer, but maybe simpler:
sapply(1:(length(v2)-1), function(j) sum(v1*v2[j:j+1]))
Since you're only multiplying vectors (aka 1-by-N matrices :-) ), there's no need to dive into the matrix ops.
Another option:
na.omit(filter(v2, rev(v1)))
You could also use embed:
apply(embed(v2, 2), 1, FUN='%*%', rev(v1))

Resources