CptNemo
CptNemo

Reputation: 6755

Is it possible to keep memory while using apply()?

I need to run the function lapply on a activation_status list t times so that the t iteration of the function remembers the results from the t-1 iteration.

The list is basically a bidimensional array representing a single item i status over multiple t periods and looks like this:

n_items <<- 100
n_iterations <<- 10

activation_status <- 
  lapply(1:n_iterations, 
         FUN = function(t, bool, i) rep(bool, t), 
         FALSE, n_items)

Now during each iteration t, I randomly activate (set to TRUE) a number of items within the list but I want all the items already activated at time t-1 to stay active (note that I define activation_status within the update function so that it's accessible in the inner functions).

updateActivation <- function(t) {
  activation_status[[t]] <- as.logical(rbinom(n_items, 1, prob = .5))
  activation_status[[t]][activation_status[[t-1]] == TRUE] <- TRUE
}

But then

lapply(1:n_iterations, updateActivation)

throws as error:

Error in activation_status[[t - 1]] : attempt to select less than one element in get1index

I know I could use a loop, but I wonder if it is:

  1. Possible to do something like this with the apply function?
  2. Do it faster?

Upvotes: 0

Views: 88

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 389135

We could probably do this without using any apply command.

#Set seed for reproduciblity
set.seed(123)
#Create initialization demo data
activation_status <- rep(FALSE, 10)
#Number of values to select
n_iterations <- 5
#Sequence from 1:n_iterations
seq_n_iterations <- seq_len(n_iterations)
#Create matrix to hold output
output <- replicate(n_iterations, activation_status)
#Select n_iterations random values from 1:length(activation_status)
#You can change this if you want to use some specific distrubution
points <- sample(length(activation_status), n_iterations)
#Create column indices
cols <- rep(seq_n_iterations, seq_n_iterations)
#Create row indices
rows <- points[ave(inds, inds, FUN = seq_along)]
#Change those values to TRUE
output[cbind(rows, cols)] <- TRUE

output
#       [,1]  [,2]  [,3]  [,4]  [,5]
# [1,] FALSE FALSE FALSE FALSE FALSE
# [2,] FALSE FALSE  TRUE  TRUE  TRUE
# [3,]  TRUE  TRUE  TRUE  TRUE  TRUE
# [4,] FALSE FALSE FALSE FALSE FALSE
# [5,] FALSE FALSE FALSE FALSE FALSE
# [6,] FALSE FALSE FALSE FALSE  TRUE
# [7,] FALSE FALSE FALSE FALSE FALSE
# [8,] FALSE FALSE FALSE  TRUE  TRUE
# [9,] FALSE FALSE FALSE FALSE FALSE
#[10,] FALSE  TRUE  TRUE  TRUE  TRUE

If you want them as lists :

asplit(output, 2)

#[[1]]
# [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

#[[2]]
# [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

#[[3]]
# [1] FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

#[[4]]
# [1] FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE

#[[5]]
# [1] FALSE  TRUE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE

Upvotes: 0

Karolis Koncevičius
Karolis Koncevičius

Reputation: 9656

Not sure if I fully understood the question but seems like you are looking for a recursion.
In that case Reduce() can be used instead of lapply():

activation_status <- rep(FALSE, 10)
n_iterations      <- 5
Reduce(function(y, x) as.logical(rbinom(length(y), 1, prob=0.1)) | y,
       x=1:n_iterations, init=activation_status, accumulate=TRUE
       )

[[1]]                                                           
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

[[2]]                                                           
 [1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE

[[3]]                                                           
 [1] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE

[[4]]                                                           
 [1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE

[[5]]                                                           
 [1]  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE

[[6]]                                                           
 [1]  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE

Upvotes: 1

Related Questions