3

I have a simple function in the R language, for instance:

f<-function(x){
y=(x+2)/3
return(y)
}

I want to evaluate this function five times on its own outputs, i.e., y1=f(x), y2=f(f(x)), y3=f(f(f(x))), y4=f(f(f(f(x)))), y5=f(f(f(f(f(x))))). Is there a simpler way to do it in the form of one function, for instance the function with two arguments when the first argument is x and the second argument is the number of evaluation times, i.e., n. For instance, for x=3 and n=5 I would like to have the function f2<-(x=3,n=5) whose output would be in the form of a vector or a list of the length equal to n with the values:

y1=f(3)=1.666667
y2=f(f(3))=1.222222
y3=f(f(f(3)))=1.074074
y4=f(f(f(f(3))))=1.024691
y5=f(f(f(f(f(3)))))=1.00823

How to write such one function in the R ?

4 Answers 4

4

Using the accepted answer in another post, just use Reduce to create the composition, g.

composite <- function(g, h) {function(...)g(h(...))}
g <- Reduce(composite, list(f, f, f, f, f))

g(2)
f(f(f(f(f(2)))))

identical(g(2), f(f(f(f(f(2))))))
#[1] TRUE
Sign up to request clarification or add additional context in comments.

2 Comments

Using replicate(5, f) to create the list of the function replicated would make this a bit more easily extendable.
@Dason Right, thanks, I hadn't thought of that. I had tried rep(f, 5) but it doesn't work.
3

You can write a helper function like:

iterate <- function(f,s,n){
  iterates <- vector(length = n+1)
  iterates[1] <- s
  for(i in 1:n){
    iterates[i+1] <- f(iterates[i])
  }
  iterates
}

Then, for example,

> iterate(function(x){(x+2)/3},3,5)
[1] 3.000000 1.666667 1.222222 1.074074 1.024691 1.008230

You can of course modify the above code so that the vector would start with f(s) rather than s.

Comments

2

You can also tweak your original function like below:

f2<-function(x, steps){
             ans<-c(x)
              for (i in 1:steps) {
                   y=(x+2)/3
                   ans=append(ans,y)
                   x = y
  }
    return(ans)
}

f2(3,5)
#> [1] 3.000000 1.666667 1.222222 1.074074 1.024691 1.008230

Comments

1

Reduce will do this if you add a "junk" argument to your f. If you just want the last result set accumulate = F or just remove the accumulate argument from the function

f<-function(x, junk){
y=(x+2)/3
return(y)
}

Reduce(f, x = numeric(5), init = 3, accumulate = T)
# [1] 3.000000 1.666667 1.222222 1.074074 1.024691 1.008230

Or with purrr

purrr::accumulate(numeric(5), f, .init = 3)
# [1] 3.000000 1.666667 1.222222 1.074074 1.024691 1.008230

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.