1

I have a very simple loop trying to draw four curves on the same graph using ggplot. Here is the code:

  df = data.frame(x=0:10/10)
  gg = ggplot(df)
  for (t in 4:1/4)
      gg = gg + geom_path(aes(x,x^t))
  gg  

When I run it, it only shows the last graph. If I add them one at a time, eg:

  df = data.frame(x=0:10/10)
  gg = ggplot(df)
  gg = gg + geom_path(aes(x,x^1.00))
  gg = gg + geom_path(aes(x,x^0.75))
  gg = gg + geom_path(aes(x,x^0.50))
  gg = gg + geom_path(aes(x,x^0.25))
  gg

it works just fine. Can someone explain the magic?

2
  • 1
    you need to capture the environment (current value of t at each stage) otherwise only the last one will exist by the time ggplot2 actually builds the plot Commented Feb 14, 2017 at 5:46
  • Have you checked out this solution? Commented Feb 14, 2017 at 5:47

3 Answers 3

4

Baptiste suggested to create the entire data.frame with all variables first, and then plot it (preferably in long format). The answer provided by Gene creates the data in wide format requiring to loop over the columns.

The code below creates the data in long format and plots all curves in one call:

# create data in long format
df <- expand.grid(x = 0:10/10, exp = 1:4/4)
df$y <- df$x^df$exp

# plot
library(ggplot2)
gg <- ggplot(df, aes(x, y, group = exp)) + geom_line()
gg

enter image description here

Note that geom_line() is used here because it connects the observations in order of the variable on the x axis. geom_path() connects the observations in the order in which they appear in the data.

The different curves can be colour-coded as well:

# continous scale
gg + aes(colour = exp)

enter image description here

# discrete scale
gg + aes(colour = factor(exp))

enter image description here

Note that by including the colour aesthetic in the call to aes() an appropriate legend is created by default.

Sign up to request clarification or add additional context in comments.

1 Comment

I accepted this, even though the answer by @baptiste is short and says more. It was so terse that I could not understand what what meant by long format vs wide, until I saw the other this answer.
4

you could substitute the value explicitly,

eval(substitute(expr = {gg = gg + geom_path(aes(x,x^t))}, env = list(t=t)))

but a better solution would be to create the entire data.frame with all variables first, and then plot it (preferably in long format).

Comments

1

As alluded to by baptise and the aforementioned solution, the for loop doesn't work because of lazy evaluation. Here's a working for loop approach that works by updating the supplied data in every loop. As mentioned elsewhere, there are more efficient ways to plot this

#make the data and put it all into a single df
df = data.frame(x=0:10/10)
df = cbind(df,sapply(4:1/4, function(t) df$x^t))

# initiate ggplot
g <- ggplot(df)

# make some colours
cols = colorRampPalette(c("blue",'green'))(ncol(df))

# loop over columns
for (j in 2:ncol(df)){

  # update the data within the loop
  gg.data <- data.frame(x = df[,1], y = df[,j])

  # add the line
  g <- g + geom_path(data = gg.data, aes(x,y), col = cols[j])
}
g

g plot

3 Comments

@Baptiste suggested to create the data in long format. Your answer creates the data in wide format which is less preferable for ggplot2 and requires to loop over the columns unnecessarily. Therefore, your statement Here's the right approach is quite strong.
@UweBlock, in some instances, such as the solution link, the for loop is inevitable. Moreover, the OP was concerned for why the for loop wasn't working hence the response. If it were my code, I would put the data into a long format and let ggplot take care of the details too.
I agree that for loops can't be avoided some times. But they are not the proper solution neither in this case nor the in the linked solution because the whole approach in both cases was misguided. To me, both cases are XY problems. Both OP experienced an issue with adding layers to a ggplot object within a for loop because they hadn't created the data in the format that ggplot prefers. A better question would have been, e.g., "How to prepare the data to plot parameterized curves with ggplot?".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.