Reputation: 4239
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
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