Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
452 views
in Technique[技术] by (71.8m points)

r - Add multiple curves / functions to one ggplot through looping

I want to add multiple curves to one ggplot. With the normal plot and curve(add=TRUE) i can loop the curve function and can add multiple curves/functions.

Since i want to rewrite my code for ggplot, i'm trying to figure out how achieve this with ggplot.

I'm using the stat_function and a for loop, but ggplot is not adding the curve, just saving the last one.

Minimum reproducible example with a single line:

library(ggplot2)
p1<-ggplot()
for (i in 1:10){
  p1<- p1 + stat_function(aes(x=1:200),fun = function(x) {x+i*3}, col=i)
  print(p1)
}

What i think the code should do:

I loop multiple stat_function and adding it to my plot p1

What i want to do:

I want alle lines to be added in one plot(p1). The code as it is, just shows the last line of the loop, as if it is overwriting the plot always, but as far as i understand ggplot this should just add a line. Also an explanation why this does not work would be nice, maybe i just don't understand ggplot here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The issue is that all the stat_functions you are refer to the same i variable. And as a consequence, each function you add will overlay perfectly with the others.

The solution is to reassign the variable in a local scope, to make a local copy for each iteration:

p1 = ggplot(data.frame(x = 1 : 200)) + aes(x)

for (i in 1:10){
    p1 = local({
        j = i
        p1 + stat_function(fun = function(x) x + j * 3, col = j)
    })
}

To make matters more confusing, you don’t actually have to give the local variable a new name; you could just as easily have written i = i, and continued to use i. The reason is that this assignment will generate a new local variable i that masks the non-local variable i. I hope we can agree that writing such code is confusing, and a bad idea.

I’ve also taken the liberty of simplifying your code slightly by moving the data x out of the stat_function, and into the ggplot object directly.

However, it is altogether cleaner not to use a loop and reassignment here. Instead you can use lapply or map (from the purrr package):

p1 = ggplot(data.frame(x = 1 : 200)) +
    aes(x) +
    map(
        1 : 10,
        ~ stat_function(fun = function (x) x + .x * 3, color = .x)
    )

This is shorter, more readable (it focuses on the “what” rather than the “how”, i.e. the mechanics of the loop), and it uses a single assignment.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...