2

I am trying to build a user-defined function which basically returns a ggplot of multiple function curves in a single plot. The plot will be a complex version of the plot below:

library(ggplot2)
 p <- ggplot() + xlim(0,4) + xlab("x")
 p <- p + geom_function(fun = function(x) 1*x)
 p <- p + geom_function(fun = function(x) 2*x)
 p <- p + geom_function(fun = function(x) 3*x)
 p <- p + geom_function(fun = function(x) 4*x)
 p

Unfortunately, I am not being able to plot it using a user defined function as below. It only returns me the last plot:

plot_func <- function(i) {
   p <- ggplot() + xlim(0,i) + xlab("x")
   for (i in 1:i) {
     p <- p + geom_function(fun = function(x) i*x)
   }
   print(p)
 }
plot_func(4)

Can anyone please tell me how to plot this using a user-defined function? Thank you very much!!

1

2 Answers 2

1

1) Add an i argument to the function and specify it in args= like this:

library(ggplot2)
plot_func1 <- function(i) {
   p <- ggplot() + xlim(0,i) + xlab("x")
   for (i in 1:i) {
     p <- p + 
        geom_function(fun = function(x, i) i*x, args = list(i = i))
   }
   print(p)
 }
plot_func1(4)

2) or use bquote:

library(ggplot2)
plot_func2 <- function(i) {
   p <- ggplot() + xlim(0,i) + xlab("x")
   for (i in 1:i) {
     p <- p + geom_function(fun = bquote(function(x) .(i)*x))
   }
   print(p)
 }
plot_func2(4)

3) or substitute i into the function like this:

library(ggplot2)
plot_func3 <- function(i) {
   p <- ggplot() + xlim(0,i) + xlab("x")
   for (i in 1:i) {
     p <- p + geom_function(fun = substitute(function(x) i*x, list(i = i)))
   }
   print(p)
 }
plot_func3(4)

4) or define the function as a character string with i substituted in and then parse it and convert it to a call object using [[1]]:

library(ggplot2)
plot_func4 <- function(i) {
   p <- ggplot() + xlim(0,i) + xlab("x")
   for (i in 1:i) {
     p <- p + 
        geom_function(fun = parse(text = sprintf("function(x) %d*x", i))[[1]])
   }
   print(p)
 }
plot_func4(4)
Sign up to request clarification or add additional context in comments.

5 Comments

AWESOME!! Thank you very much for your solutions!! They all work perfectly. I didn't get any solution like this before from any book or post.
I've a doubt regarding why 1st option work. Is it the case if supplied via args, it'll force evaluation? I was trying to do the same thing when OP cross-posted on RStudio Community, and I had to use local to solve the issue. Otherwise, it was always taking latest updated value of the counter.
It works for me. Just copy the code and paste it into R and when I do that it gives 4 lines.
I think you misunderstood. Yours work fine for me. I am asking why OP's method failed. If I specify with args, what's the speciality? Does it force evaluation at that point? Or, something else?
In that case it would make more sense to post your comment under the question.
1

Consider the functional form of running ggplots by calling its + (via undocumented +.gg() method) inside Reduce on list of aesthetic layers:

plot_func <- function(i) {
  layers <- list(ggplot(), 
                 xlim(0, i),  
                 xlab("x"),
                 lapply(1:i, function(i) geom_function(fun = function(x) i*x)))
  
  p <- Reduce(ggplot2:::`+.gg`, layers)
  print(p)
}

plot_func(4)

1 Comment

Thank you very much!! Your solution works as well, and is pretty unique!!

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.