Home > database >  In R, how to first use a loop to create matrices and then stack them?
In R, how to first use a loop to create matrices and then stack them?

Time:11-17

I'm looking to do the following: 1° Use a loop in R to create matrices 2° Once these matrices are created I want to stack them

For example I have tried : (please see inside the code what I try to do)

S = 5
n = 100
B = 2
alpha=0.3
beta=1.2

sim_original_samples <- matrix(0, S , n) 
sim_original_samples_X_bar <- matrix(0, S, 1)

for (i in 1:S) {
sim_original_samples[i,] <- rgamma(n, alpha, beta)
# here I simulate 5 samples from a gamma distribution 
sim_original_samples_X_bar[i] <- mean(sim_original_samples[i])
# here I compute the sample average for each one
##
  for (j in 1:B) {
      matrix_j <- sample(sim_original_samples[i],n,replace=TRUE)
# for each sample i, I want to draw a new sample 
# I want to repeat this B times 
# thus matrix_j is a (1*n) matrix of the observations 
# instead of writing matrix_1 = ... , matrix_B = ... I want to loop this 
# however, this command doesn't work 
#
# next once I have created this B matrices per sample i I want to compute the sample average
     matrix_j_av <- mean(matrix_j)
# again, I want to do this for every matrices from 1 to B 
# 
# next, I want to stack these matrices 
# first the matrix of all samples 
    matrix_big <- list(matrix_j)
# that is, its first element is for the original sample n°1, the first resampling 
# its second element is, for the original sample n°2, the second resampling 
# and so on, last element, for sample n°S, resampling n°B
# I guess this matrix is of dimension S*B * n
#
# I want to do exactly the same for the matrix of sample means 
   matrix_big_sample <- list(mean_matrix_j)
# which I guess is of dimension S*B * 1

How do I do all of this ? PS : for those of you who had a doubt, yes it is Bootstrap method ;)

CodePudding user response:

The Question

Let's divide your question into a two parts:

  1. How to create the data: samples, re-samples, means, etc.
  2. How to create a multi-dimensional object

1. Creating the data

Configuration from your question

S     <-   5
n     <- 100
B     <-   2
alpha <-   0.3
beta  <-   1.2

Sample and re-sample

require( tidyverse )
U    <- map_dfc( 1:S, ~rgamma( n, alpha, beta ))
Ubar <- map_dfc( 1:S, mean )
V    <- map_dfc( 1:S, ~sample( U[[ . ]], n, replace = TRUE ))
Vbar <- map_dfc( 1:S, mean )

What shape are these?

dim( U )
#  100   5

dim( V )
#  100   5

dim( Ubar )
#    1   5

dim( Vbar )
#    1   5

Now, what did you want to stack? (and why?)




2. How to create a multi-dimensional object

Sometimes it can be helpful to pack data into a multi-dimensional object, in order to facilitate slicing along axes, or to select specific elements.

Define the object


multi_dimensional <- array(
    data = 0:( S * B * n )
  , dim  = c( S, B, n )
  , dimnames = list(             # <---- names are optional
        paste0( 'X', 1:S )
      , paste0( 'Y', 1:B )
      , paste0( 'Z', 1:n )
    )
)

dim( multi_dimensional )
# [1]   5   2 100

Slice, dice, and chop

multi_dimensional[ 1, 1, 1 ]
# [1] 0

multi_dimensional[ S, B, n ]
# [1] 999

multi_dimensional[ 1, 2, 1:10]
# Z1  Z2  Z3  Z4  Z5  Z6  Z7  Z8  Z9 Z10 
#  5  15  25  35  45  55  65  75  85  95 

multi_dimensional[ , , 1:2 ]
# , , Z1
# 
#    Y1 Y2
# X1  0  5
# X2  1  6
# X3  2  7
# X4  3  8
# X5  4  9
# 
# , , Z2
# 
#    Y1 Y2
# X1 10 15
# X2 11 16
# X3 12 17
# X4 13 18
# X5 14 19


multi_dimensional[ S, B, 99:100 ]
# Z99 Z100 
# 989  999 

Use the named dimensions, if you wish

multi_dimensional[ , , c( 'Z1', 'Z2' ) ]
# , , Z1
# 
#    Y1 Y2
# X1  0  5
# X2  1  6
# X3  2  7
# X4  3  8
# X5  4  9
# 
# , , Z2
# 
#    Y1 Y2
# X1 10 15
# X2 11 16
# X3 12 17
# X4 13 18
# X5 14 19

multi_dimensional[ c( 'X1', 'X3', 'X5' ), 'Y2' , c( 'Z1', 'Z2' ) ]
#    Z1 Z2
# X1  5 15
# X3  7 17
# X5  9 19

Assign new values to specific elements

multi_dimensional[ 5, 1, 29:30 ] <-  c( 124.76, -5.0002 )

Now show the new values

multi_dimensional[ 5, 1, 29:30 ]
#  Z29   Z30 
# 124.8  -5.0 

multi_dimensional[ 1:3, , 91:100 ]  # slice off a particular 3 x 10 block
# (not shown, due to size)

CodePudding user response:

I think you misunderstoond the purpose of matrix datatype as in R matrices can't store complex objects such as other matrices, they are limited to: double/numeric, integer, logical, character, complex and raw.

What you seem to want is to be able to store a list of B matrices of arbitrary size (1 by n) that are generated on the second loop. You can declare an empty list and start adding the matrices in the second loop to it with something like this:

#You can declare this outside the loops.
matrix_j <- vector(mode='list', length=B)
#Then on the inner loop you can use [[]] to add elements to a list
for (j in 1:B) {
      matrix_j[[j]] <- sample(sim_original_samples[i],n,replace=TRUE)

or if you want an empty list of size 0, you can do matrix_j <- list() instead.

Next i didn't get if you want to compute the mean of each sample inside the list or if you want to compute the mean of the whole set of numbers, so:

  1. First one would require you to you use the list apply function lapply,like this: lapply(matrix_j,mean), which would return a list in which each element is the mean of the the element in the same position of matrix_j.
  2. For the second possibility, i think it would be more appropriate to combine the list elements into one simpler data structure and then compute the mean.

For your last problem, it seems to me that using lists (lists of lists) would solve your issue. I'd create a big empty list and then add other lists as elements, as lists are allowed to contain other lists.

  • Related