Loop Matrix to store in Cube - r

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.

Related

How to apply a function on every element of all elements in a list in R

I have a list containing matrices of the same size in R. I would like to apply a function over the same element of all matrices. Example:
> a <- matrix(1:4, ncol = 2)
> b <- matrix(5:8, ncol = 2)
> c <- list(a,b)
> c
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 5 7
[2,] 6 8
Now I want to apply the mean function and would like to get a matrix like that:
[,1] [,2]
[1,] 3 5
[2,] 4 6
One conceptual way to do this would be to sum up the matrices and then take the average value of each entry. Try using Reduce:
Reduce('+', c) / length(c)
Output:
[,1] [,2]
[1,] 3 5
[2,] 4 6
Demo here:
Rextester
Another option is to construct an array and then use apply.
step 1: constructing the array.
Using the abind library and do.call, you can do this:
library(abind)
myArray <- do.call(function(...) abind(..., along=3), c)
Using base R, you can strip out the structure and then rebuild it like this:
myArray <- array(unlist(c), dim=c(dim(a), length(c)))
In both instances, these return the desired array
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
step 2: use apply to calculate the mean along the first and second dimensions.
apply(myArray, 1:2, mean)
[,1] [,2]
[1,] 3 5
[2,] 4 6
This will be more flexible than Reduce, since you can swap out many more functions, but it will be slower for this particular application.

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!

Subset matrix with arrays in r

It is probably fairly basic but I have not found an easy solution.
Assume I have a three-dimensional matrix:
m <- array(seq_len(18),dim=c(3,3,2))
and I would like to subset the matrix with the arrays of indexes:
idxrows <- c(1,2,3)
idxcols <- c(1,1,2)
obtaining the arrays in position (1,1),(2,1) and (3,2), that is:
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 10 14 18
I have tried m[idxrows,idxcols,] but without any luck.
Is there anyway to do it (without obviously using a for loop)?
Not sure if there is any easy built in extract syntax, but you can work around this with mapply:
mapply(function(i, j) m[i,j,], idxrows, idxcols)
# [,1] [,2] [,3]
#[1,] 1 2 6
#[2,] 10 11 15
Or slightly more convoluted, create a index matrix whose columns match the dimensions of the original array:
thirdDim <- dim(m)[3]
index <- cbind(rep(idxrows, each = thirdDim), rep(idxcols, each = thirdDim), 1:thirdDim)
matrix(m[index], nrow = thirdDim)
# [,1] [,2] [,3]
#[1,] 1 2 6
#[2,] 10 11 15

Matrix without the matrix function

I m trying to create a matrix in R without using matrix function I tried
this but it works just for 2 rows how do I specify nrows I have no idea
matrix2<-function(n)
{
d<-n/2
v1<-c(1:d)
v2<-c(d +1:n)
x<- rbind(v1,v2)
return(x)
}
I want to create a matrix without using the matrix function and byrow not bycolmun
exemple
a function I enter number of columns and the dimension N in my exemple and in return it creates a matrix
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
[4,] 7 8
for exepmle
This will give you a matrix for a specified number of columns. I wasn't sure what you meant with dimension N.
matrix2 <- function(N, columns){
d<-ceiling(N/columns) # rounds up to first integer
x <- c()
i <- 1
for(row in 1:d){
x <- rbind(x, c(i:(i+columns-1)))
i <- i+columns
}
return(x)
}
> matrix2(8,2)
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
[4,] 7 8
You can also use an indirection via a list. Then you can also set both, the column and the row number. And how the matrix is filled, row wise or column wise.
matrix2<-function(n,m,V,byRow=T){
if(length(V) != n*m ) warning("length of the vector and rows*columns differs" )
# split the vector
if(byRow) r <- n
if(!byRow) r <- m
fl <- 1:r # how often you have to split
fg <- sort(rep_len(fl,length(V))) # create a "splitting-vector"
L <- split(V,fg)
# convert the list to a matrix
if(byRow) res <- do.call(rbind,L)
if(!byRow) res <- do.call(cbind,L)
rownames(res) <- colnames(res) <- NULL
res #output
}
matrix2(2,4,1:8,F)
[,1] [,2] [,3] [,4]
[1,] 1 3 5 7
[2,] 2 4 6 8
matrix2(2,4,1:8,T)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8

How to slice a n dimensional array with a m*(n-i) dimensional matrix?

If i have a n dimensional array it can be sliced by a m * n matrix like this
a <- array(1:27,c(3,3,3))
b <- matrix(rep(1:3,3),3)
# This will return the index a[1,1,1] a[2,2,2] and a[3,3,3]
a[b]
# Output
[1] 1 14 27
Is there any "effective and easy" way to do a similar slice but to keep some dimensions free?
That is slice a n dimensional array with a m * (n-i) dimensional array and
get a i+1 dimensional array as result.
a <- array(1:27,c(3,3,3))
b <- matrix(rep(1:2,2),2)
# This will return a vector of the index a[1] a[2] a[1] and a[2]
a[b]
# Output
[1] 1 2 1 2
# This will return the indexes of the cartesian product between the vectors,
# that is a array consisting of a[1,,1] a[1,,2] a[2,,1] and a[2,,2]
a[c(1,2),,c(1,2)]
# Output
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
, , 2
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
The desired result should be if the last command returned an array
with a[1,,1] and a[2,,2].
For now I solve this the problem with a for loop and abind but I'm sure there must be a better way.
# Desired functionality
a <- array(1:27,c(3,3,3))
b <- array(c(c(1,2),c(1,2)),c(2,2))
sliceem(a,b,freeDimension=2)
# Desired output (In this case rbind(a[1,,1],a[2,,2]) )
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 11 14 17
I think this is the cleanest way -- making a separate function:
slicem <- function(a,idx,drop=FALSE) do.call(`[`,c(list(a),idx,list(drop=drop)))
# usage for OP's example
a <- array(1:27, c(3,3,3))
idx <- list(1:2, TRUE, 1:2)
slicem(a,idx)
which gives
, , 1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
, , 2
[,1] [,2] [,3]
[1,] 10 13 16
[2,] 11 14 17
You have to write TRUE for each dimension that you aren't selecting from.
Following the OP's new expectations...
library(abind)
nistfun <- function(a,list_o_idx,drop=FALSE){
lens <- lengths(list_o_idx)
do.call(abind, lapply(seq.int(max(lens)), function(i)
slicem(a, mapply(`[`, list_o_idx, pmin(lens,i), SIMPLIFY=FALSE), drop=drop)
))
}
# usage for OP's new example
nistfun(a, idx)
# , , 1
#
# [,1] [,2] [,3]
# [1,] 1 4 7
#
# , , 2
#
# [,1] [,2] [,3]
# [1,] 11 14 17
Now, any non-TRUE indices must have the same length, since they will be matched up.
abind is used here instead of rbind (see an earlier edit on this answer) because it is the only sensible general way to think about slicing up an array. If you really want to drop dimensions, it's quite ambiguous which should be dropped and how, so the vector alone is returned:
nistfun(a, idx, drop=TRUE)
# [1] 1 4 7 11 14 17
If you want to throw this back into an array of some sort, you can do that after the fact:
matrix( nistfun(a, idx), max(lengths(idx)), dim(a)[sapply(idx,isTRUE)]), byrow=TRUE)
# [,1] [,2] [,3]
# [1,] 1 4 7
# [2,] 11 14 17

Resources