Cris
Cris

Reputation: 335

How to add 'stat_function()' layers in ggplot2 using a for loop?

I have several similar dataframes and a non linear regression for each dataset. I would like to overlay the plots using a for cycle as long as initially I don't know how many data frames are there. I can overlay the geom_point() layers using a for() cycle but when I tried the same using stat_function() only the last function is plotted.

How can I get the same result for the functions as I got for the points?

MWE:

library(ggplot2)
# Colors vector
hues = seq(15, 375, length = 10 + 1)
cols = hcl(h = hues, l = 65, c = 100)[1:10]

# Create plot and add first layer
p <- ggplot(data = data.frame(x = 1:10, y = 10 + 1:10), 
             aes(x = x, y = y, color = cols[i])) +
      geom_point()

# Add points of other datasets
for (i in 1:9) {
  p <- p + geom_point(data = data.frame(x = 1:10, y = i + 1:10), color = cols[i])   
}
print(p)

# This for cycle only seems to work for the last layer
for (i in 1:10) {
  p <- p + stat_function(fun = function(x) (i + x), color = cols[i]) 
}
print(p)

Thank you in advance.

Upvotes: 1

Views: 641

Answers (2)

Phil
Phil

Reputation: 8107

When adding layers dynamically, I prefer to think of the ggplot object as a list of layers, so it's a question of building layers into a list. You can either use lapply() or purrr::map(), here I'm choosing the latter:

lines <- purrr::map(1:10, function(y) stat_function(fun = function(x) (y + x), color = cols[y]))

p + lines

enter image description here

Upvotes: 1

MrFlick
MrFlick

Reputation: 206167

A for loop doesn not create environments to capture i values for you. So you are creating the same function each time with a a free varaible i and that value is not "looked-up" until the plot is printed and after the for loop the value of i is just 10.

Instead, you should capture the value in the layer with the args= command. Those will be evaluated during the loop, not at draw time. Then just add the variable you captured as a parameter to the function.

for (i in 1:10) {
  p <- p + stat_function(fun = function(x, i) (i + x), color = cols[i], args=list(i=i)) 
}
print(p)

Upvotes: 4

Related Questions