Plotting multiple function curves in a single plot using ggplot() in a user-defined function

Hello everyone,

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, which basically plots 4 curves in one plot:

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, out of the four plots:

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!!

library(ggplot2)

ggplot() + 
  xlim(0,4) + 
  xlab("x") +
  geom_function(fun = function(x) 1*x) +
  geom_function(fun = function(x) 2*x) +
  geom_function(fun = function(x) 3*x) +
  geom_function(fun = function(x) 4*x)

Created on 2020-12-31 by the reprex package (v0.3.0.9001)

Hello!!

Thanks for your response!! Sorry if I was not clear enough with the question but I want to achieve the plot using a for loop inside a user-defined function, as mentioned in the second set of codes in my question.

With a for loop, it's easy to over-write all the previous values with the last value through the loop. Remember that the intermediate value do not get saved to the global environment unless explicitly assigned to an external object.

I think that the problem is not related to global environment, since @Aru has defined everything inside a function, so all in same environment.

The issue is lazy evaluation. When new layers are added, those are not evaluated at that point. Here's a link with more details:

Unfortunately, I don't have a good solution. Here's something that will work:

library(ggplot2)

plot_slopes <- function(maximum_slope)
{
    slope_layers = list()
    for (slope in seq.int(maximum_slope))
    {
        layer_function <- local({local_slope <- slope; function(placeholder_variable) local_slope * placeholder_variable})
        slope_layers[[slope]] <- geom_function(fun = layer_function)
    }

    plot_object <- ggplot() + xlim(0, 4) + xlab("x") + slope_layers

    return(plot_object)
}

plot_slopes(5)

This I created based on this, but I do hope that someone will give a better solution:

Hope this helps.

2 Likes
suppressPackageStartupMessages({
  library(ggplot2)
  library(purrr)
})


# blank canvas

x_arg <- c(1,2,3,4)
y_arg <- c(5,6,7,8)

receiver <- ggplot() + xlim(0,4) + xlab("x")

mk_plots <- function(x,y) geom_function(fun = function(x) x*y) 

receiver + unlist(map2(x_arg,y_arg,mk_plots))

Created on 2021-01-01 by the reprex package (v0.3.0.9001)

1 Like

Here's an approach similar to technocrat (function factory and purrr::map style looping)
but based on the idea of concretizing the data (i.e. you might export the data as well as plot it)
the plotting can then be simpler as it directly plots the data its provided rather than calculating 'on the fly'

suppressPackageStartupMessages({
  library(tidyverse)
})

y_arg <- c(5, 6, 7, 8)

mk_plots <- function(y) {function(x) {x * y}}

in_1 <- data.frame(x = seq(
  from = 0,
  to = 4,
  by = 0.01
))

(in_2 <- mutate(in_1,
  across(x,
    map(y_arg, ~ mk_plots(y=.))
  )))

(in_3 <- pivot_longer(in_2, cols = -x))

ggplot(data = in_3) +
  # xlim(0, 4) +
  xlab("x") +
  aes(x = x, y = value, colour = name) +
  geom_line()

2 Likes

Thank you very much everyone for your solutions!!
Here is a link of some other solutions that I got from Stack Overflow: https://stackoverflow.com/questions/65526367/can-i-plot-multiple-function-curves-in-a-single-plot-using-ggplot-in-a-user-de