4

I'm interested in plotting multiple functions in ggplot2 using stat_function. I have tried the solutions suggested here and here, but I continue to only get one function in my final figure. Overall, I want multiple quadratic functions, each spanning different lengths on the x-axis, and each in the color specified in the color column.

Here is a quick example of the data, with three quadratic functions:

intercept <- c(0.23, 0.53, 0.41)
linear <- c(0.02, 0.05, 0.04)
quad <- c(-0.01, 0.01, 0.01)
limit <- c(5, 18, 27)
color <- c('#1400E5', '#800C74', '#EC1804')
data <- data.frame(intercept, linear, quad, limit, color)

Here is the first thing I tried, which only outputs the final function in the figure:

p <- ggplot(data=data.frame(x=c(0,0))) +
  ylim(c(0,1)) +
  xlim(c(0,28))

for (i in 1:length(data$quad))
  p <- p + stat_function(aes(y=0), fun=function(x) data[i,'quad']*x^2 + data[i,'linear']*x + data[i,'intercept'], xlim=c(0, data[i,'limit']), colour=data[i,'color'])

print(p)

The result is the warning: Warning messages: 1: Removed 68 rows containing missing values (geom_path). 2: Removed 79 rows containing missing values (geom_path).

Here is the second thing I tried, which also only outputs the final function in the figure:

lines <- alply(data, 1, function(row) { 
  stat_function(fun=function(x) row['quad'] * x^2 + row['linear'] * x + row['intercept'], xlim=c(0,row['limit']), color=row['color'])  
})

ggplot(data=data.frame(x=c(0,0))) +
  lines +
  scale_y_continuous(limits=c(0,1)) +
  scale_x_continuous(limits=c(0,28))

The result is the warning: Warning messages: 1: Computation failed in stat_function(): default method not implemented for type 'list' 2: Computation failed in stat_function(): default method not implemented for type 'list' 3: Computation failed in stat_function(): default method not implemented for type 'list'

I've also tried making the dataframe into a matrix in the alply step, which produced a different error, but still didn't work.

Any advice would be appreciated. Thanks!

Community
  • 1
  • 1
Kim L
  • 41
  • 2
  • I came across the same problem: It looks like that using stat_function in a loop with the variable of the loop as an argument to the function always produces `n` functions with the last value of the loop variable. – reox Aug 06 '18 at 08:54
  • I now found out that using the loop variable as an argument in the `args` argument in `stat_function` works, while using it as an argument in `fun` does not. – reox Aug 06 '18 at 09:52

1 Answers1

1

I can see this is an old question. As of Sep 2019, I tried to ran the code and found stat_functions when overlayed with a for loop, can only plot the last one.

Suggestions including starting from scratch with simulated data and such. I am still confused as to why this cannot be done. However, using tidy evaluation methods, I am able to solve the problem for myself and would like to present it below.

Basically writing up the many layers were tedious error-prone, so we just want to construct the ggplot2 commands expressions programmatically.

library(tidyverse)
library(rlang)

intercept <- c(0.23, 0.53, 0.41)
linear <- c(0.02, 0.05, 0.04)
quad <- c(-0.01, 0.01, 0.01)
limit <- c(5, 18, 27)
color <- c('#1400E5', '#800C74', '#EC1804')
data <- data.frame(intercept, linear, quad, limit, color)

p <- expr(ggplot(data=data.frame(x=c(0,0))) +
  ylim(c(0,1)) +
  xlim(c(0,28)))

for (i in 1:length(data$quad)){
  new_layer <- expr(
    stat_function(
      aes(y=0), 
      fun=function(x) data[!!i,'quad']*x^2 + data[!!i,'linear']*x + data[!!i,'intercept'], 
      xlim=c(0, data[!!i,'limit']), 
      colour=data[!!i,'color'])
    )
  p <- expr(!!p + !!new_layer)
}

eval(p)
PaulDong
  • 711
  • 7
  • 19