Avoid the for loop - r

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

Related

How to vectorize this operation?

I have a n x 3 x m array, call it I. It contains 3 columns, n rows (say n=10), and m slices. I have a computation that must be done to replace the third column in each slice based on the other 2 columns in the slice.
I've written a function insertNewRows(I[,,simIndex]) that takes a given slice and replaces the third column. The following for-loop does what I want, but it's slow. Is there a way to speed this up by using one of the apply functions? I cannot figure out how to get them to work in the way I'd like.
for(simIndex in 1:m){
I[,, simIndex] = insertNewRows(I[,,simIndex])
}
I can provide more details on insertNewRows if needed, but the short version is that it takes a probability based on the columns I[,1:2, simIndex] of a given slice of the array, and generates a binomial RV based on the probability.
It seems like one of the apply functions should work just by using
I = apply(FUN = insertNewRows, MARGIN = c(1,2,3)) but that just produces gibberish..?
Thank you in advance!
IK
The question has not defined the input nor the transformation nor the result so we can't really answer it but here is an example of adding a row of ones to to a[,,i] for each i so maybe that will suggest how you could solve the problem yourself.
This is how you could use sapply, apply, plyr::aaply, reshaping using matrix/aperm and abind::abind.
# input array and function
a <- array(1:24, 2:4)
f <- function(x) rbind(x, 1) # append a row of 1's
aa <- array(sapply(1:dim(a)[3], function(i) f(a[,,i])), dim(a) + c(1,0,0))
aa2 <- array(apply(a, 3, f), dim(a) + c(1,0,0))
aa3 <- aperm(plyr::aaply(a, 3, f), c(2, 3, 1))
aa4 <- array(rbind(matrix(a, dim(a)[1]), 1), dim(a) + c(1,0,0))
aa5 <- abind::abind(a, array(1, dim(a)[2:3]), along = 1)
dimnames(aa3) <- dimnames(aa5) <- NULL
sapply(list(aa2, aa3, aa4, aa5), identical, aa)
## [1] TRUE TRUE TRUE TRUE
aa[,,1]
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
## [3,] 1 1 1
aa[,,2]
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
## [3,] 1 1 1
aa[,,3]
## [,1] [,2] [,3]
## [1,] 13 15 17
## [2,] 14 16 18
## [3,] 1 1 1
aa[,,4]
## [,1] [,2] [,3]
## [1,] 19 21 23
## [2,] 20 22 24
## [3,] 1 1 1

How to calculate variance between observations, when observations are in matrix form each

I have a cluster of 250 observations. each observation is a 4 by 9 matrix.
4 is number of variable parameters observed and 9 is number of days, observations were collected.
I want to know the variance between 250 observations which are in matrix form. as I ve studied so far, variance is calculated among one dimension variables.
any suggestion for data in matrix form?
mat1 <- matrix(c(0:69),10,7)
mat2 <- matrix(c(3:72),10,7)
mat3 <- matrix(c(0:69),10,7)
...
var <- var(mat1,mat2, mat3,..)
for these three matrices, var() returns a 7 by 7 matrix of 9.166667 for all elements. I do not know what r is doing. or how to get to this.
I think this will reflect what you're hoping for.
First, I'll create a few matrices, very small:
set.seed(42)
mat1 <- matrix(sample(100,12),2,4)
mat2 <- matrix(sample(100,12),2,4)
mat3 <- matrix(sample(100,12),2,4)
From here, I think you want to get
var(c(mat1[1,1], mat2[1,1], mat3[1,1]))
# [1] 193
but for every set of cells in all matrices.
One way to do this is to abind all matrices into a 3D array and then use apply:
ary <- do.call(abind::abind, c(list(mat1, mat2, mat3), along = 3))
ary
# , , 1
# [,1] [,2] [,3] [,4]
# [1,] 49 25 18 47
# [2,] 65 74 100 24
# , , 2
# [,1] [,2] [,3] [,4]
# [1,] 26 41 27 5
# [2,] 3 89 36 84
# , , 3
# [,1] [,2] [,3] [,4]
# [1,] 24 43 22 8
# [2,] 30 15 58 36
apply(ary, 1:2, var)
# [,1] [,2] [,3] [,4]
# [1,] 193.0000 97.33333 20.33333 549
# [2,] 966.3333 1530.33333 1057.33333 1008
Where 193 is the variance of the [1,1] elements, 97.333 is the variance of the [1,2] elements, etc.
The arguments to var are:
> args(var)
function (x, y = NULL, na.rm = FALSE, use)
so mat1 is being passed to x and mat2 to y and mat3 to na.rm. Element i, j of the result is the covariance of x[, i] and y[, j].
The code in the question really all makes no sense and some reading of ?var would help. It is not clear what "I want to know the variance between 250 observations which are in matrix form" means. If it means that v[i, j] should be calculated as the variance of c(mat1[i,j], mat2[i, j], mat3[i, j]) then we can use one of several list comprehension packages or just iterated sapply. They all use the fact that these two are the same for fixed i and j except the first is more general.
var(sapply(L, `[`, i, j))
var(c(L[[1]][i, j], L[[2]][i,j], L[[3]][i,j]))
The syntax for the listcompr alternative seems particularly intuitive here.
L <- list(mat1, mat2, mat3)
nr <- nrow(L[[1]])
nc <- ncol(L[[1]])
library(listcompr)
v1 <- gen.matrix(var(sapply(L, `[`, i, j)), i = 1:nr, j = 1:nc)
# or
library(eList)
v2 <- Mat(for(j in 1:nc) for(i in 1:nr) var(sapply(L, `[`, i, j)))
# or (no packages):
v3 <- sapply(1:nc, \(j) sapply(1:nr, \(i) var(sapply(L, `[`, i, j))))
# checks
identical(v1, v2)
## [1] TRUE
identical(v1, v3)
## [1] TRUE
i <- 2; j <- 3
identical(v1[i, j], var(c(L[[1]][i, j], L[[2]][i,j], L[[3]][i,j])))
## [1] TRUE

Calculations between matrices in r

I have a question related to working on two matrices.
Let's assume that first matrix (P(i)) is:
x <- rmultinom(2, size = 10, prob=c(0.5,0.5))
> x
[,1] [,2]
[1,] 6 4
[2,] 4 6
..and the second matrix (Q(i)) is:
y <- rmultinom(2, size = 10, prob=c(0.5,0.5))
> y
[,1] [,2]
[1,] 6 7
[2,] 4 3
Let's assume that P(i) stands for every cell in the first matrix and Q(i) stands for every cell in the second matrix. I am trying to sum this function, (I could not find the symbol for the "Sum"):
z = (Sum)(P(i)*log(P(i)/Q(i)))
Any help would be greatly appreciated.
Thanks!

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.

Constructing a matrix as function of row and column

The situation is pretty straightforward. I want to create a matrix A of n rows and m columns, where the value for each element is given by a predetermined function f(i, j). What is the most elegant way to achieve this?
You can use outer:
outer(1:3,1:3,function(i,j) i^2+j)
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 5 6 7
[3,] 10 11 12
It would help if you provided a reproducible example, but you could do something like this:
f <- function(i,j) i*j
m <- 4
n <- 2
out <- apply(expand.grid(1:m, 1:n), 1, function(x) f(x[1],x[2]))
dim(out) <- c(m,n)

Resources