mynameisJEFF
mynameisJEFF

Reputation: 4239

Difficulty in applying a function over a sequence, when the function doesnt take the sequence as an argument

Difficulty in applying a function over a sequence, when the function doesn’t take the sequence as an argument and when the function uses values returned from the function itself at the previous value of the sequence.

I have the following problem. In my main method function mainn, I will first initialise fa, mu.a, mu.b, sigma, which will then be used as arguments in the step2 function. (Please note that I am pretty sure that my px.q4 and step2 are working correctly/properly in the sense that px.q4 returns a value and step2 returns 3 values)

This is where my question enters. I would like to perform apply step2 over a sequence, and every time it applies over the sequence (except for the first iteration), the step2 function will use NOT the initial values but the values of fa.iter, mu.a.iter, mu.b.iter from the previous step2. Can this be done in R? Or do I have to use a for-loop for this sort of question

I was able to do this using a for-loop. However, I want to learn more about R. Is there a (more efficient) particular command that I can use to get around the problem?

#this function returns a value    
px.q4 <- function(fa, mu.a, mu.b,sigma)
{   
  v <- fa + mu.a + mu.b * sigma
  v
}

#this function returns 3 values, fa.iter, mu.a.iter, and mu.b.iter
#for completeness I include the full code of what i am trying to do. 
#But all you need to know is that the function step2 returns 3 values .
step2 <- function(fa, mu.a, mu.b)
{

  #set prev = iter values // this also allow set initial values = prev in 
  #the 1st iteration
  mu.a.prev <- mu.a.iter
  mu.b.prev <- mu.b.iter
  fa.prev <- fa.iter

  #draw a trail point x.trail from propsal distribution ~ N(x_i-1,0.1)
  mu.a.trail <- rnorm(1, mu.a.prev, 0.1)
  mu.b.trail <- rnorm(1, mu.b.prev, 0.1)
  fa.trail <- rnorm(1, fa.prev, 0.1)
  while(fa.trail < 0 || fa.trail > 1)         
  {
    fa.trail <- rnorm(1, fa.prev, sigma)
  }
  #if p(x_trail) >= p(x_i-1) set x_i = x_trail
  a <- px.q4(fa.trail, mu.a.trail, mu.b.trail, sigma) 
  b <- px.q4(fa.prev ,mu.a.prev , mu.b.prev,sigma)
  if(a >= b)
  {
    mu.a.iter <- mu.a.trail
    mu.b.iter <- mu.b.trail
    fa.iter <- fa.trail
  }else{
    r <- runif(1,min = 0, max = 1)
    if(r < a/b){
      mu.a.iter <- mu.a.trail
      mu.b.iter <- mu.b.trail
      fa.iter <- fa.trail
    }else{
      mu.a.iter <- mu.a.prev
      mu.b.iter <- mu.b.prev
      fa.iter <- fa.prev
    }
  }

  res <-  list(mu.a.iter,  mu.b.iter,  fa.iter)
  res
}
#main body

mainn <- function(n,fa,mu.a,mu.b)
{
  sigma <- 0.3
  mu.a.init <- mu.a               #initial values 
  mu.b.init <- mu.b
  fa.init <- fa           #(must be between 0 and 1)

  #set initial values = iter values (for entering for loop)
  mu.a.iter <- mu.a.init
  mu.b.iter <- mu.b.init
  fa.iter <- fa.init

  #where to the logical flaw comes in and how can I overcome it
    y <- sapply(n,FUN = step2)

}

Upvotes: 2

Views: 478

Answers (1)

Vincent Zoonekynd
Vincent Zoonekynd

Reputation: 32351

You can use Reduce to apply a function recursively over a list: for instance,

Reduce(`+`, 1:10, accumulate=TRUE)

is equivalent to cumsum(1:10).

In your case, you are not applying the function over a list, but just iterating it: you can still use Reduce, if you ignore the second argument.

# It is easier if your function takes a vector and returns a vector.
# The second argument is ignored.
step2 <- function(x, u) cumsum(x) + rnorm(length(x))
r <- Reduce(step2, 1:100, init=c(0,0,0), accumulate = TRUE)

But there is nothing wrong in using a loop: it should not be significantly slower, unless your function is very fast.

Upvotes: 4

Related Questions