Search code examples
rconditional-statementssampling

Repeated sampling until condition


I am looking to sample repeatedly from a distribution with a specific condition. I am sampling 50 values for four iterations and saving the results. However I need each individual results from the iteration to be smaller than the last result at the same position.

mu.c <- c(7,6,5,3) # Means of control chains

chains.sim <- function(vector, N) {
  all.list <- list()
  
  for (i in 1:length(vector)) { 
    Y <- MASS::rnegbin(n = N, mu = vector[i], theta = 4)
    name <- paste('position:',i, sep = '')
    all.list[[name]] <- Y
  }
  all.list
}

chains.sim(mu.c, 50)

The sampling part works fine, but the Y individual results are of course not always smaller than the results from the previous iteration ("position").

Is there a way to repeat the sampling process until the result is smaller?

I would really appreciate your help!


Solution

  • I would add a while loop inside your for loop which samples data sets until the condition is met.

    mu.c <- c(7,6,5,3) # Means of control chains
    
    chain.sim <- function(vector, N) {
      all.list <- list()
      all.list[[1]] <- MASS::rnegbin(n = N, mu = vector[1], theta = 4)
      
      for (i in 2:length(vector)) { 
        is_smaller <- FALSE
        while(!is_smaller){
          Y <- MASS::rnegbin(n = N, mu = vector[i], theta = 4)
          if (all(all.list[[i-1]] >= Y)) is_smaller <- TRUE
        }
        all.list[[i]] <- Y
      }
      all.list
    }
    chain.sim(mu.c, 3)
    

    Note that I changed the condition to >=, because if 0 is generated in any round, it will never find smaller values. Also, with 50 elements this code will never stop, because it is really unlikely to get two samples where each value is smaller, let alone 4 different samples.

    Edit: it can be much faster by sampling individually as you pointed out

    chain.sim <- function(vector, N) {
      
      all.list <- list()
      all.list[[1]] <- MASS::rnegbin(n = N, mu = vector[1], theta = 4)
      
      for (i in 2:length(vector)) { 
        Y <- numeric(N)
        for (j in 1:N){
          previous_value <- all.list[[i-1]][j]
          if (previous_value == 0){
            Y[j] = 0
            next
          }
          is_smaller <- FALSE
          while(!is_smaller){
            val <- MASS::rnegbin(1, mu = vector[i], theta = 4)
            if (val <= previous_value) is_smaller <- TRUE
            Y[j] <- val
          }
        }
    
        all.list[[i]] <- Y
      }
      all.list
    }
    chain.sim(mu.c, 50)
    

    If 0 is encountered anywhere, no more simulation is necessary as we know the next value can only be 0. This makes the simulation much faster