1

I'm trying to use a loop to simplify a ggplotcommand, but it only assigns the last part of the loop to my ggplot object.

plot.test = ggplot(data = plot.df, aes(x = xvariable)) + 
  geom_line(aes(y = yvariable)) 

for (i in 1:6){
  plot.test = plot.test + geom_point(aes(y = ypoints[i], x = xpoints[i])) 
}

So, the problem is, that after running the loop, plot.test does only contain the original line and the last point from the loop, i.e. point (x[6],y[6])

Any ideas on how to solve this?

3 Answers 3

3

Why would you want to do that?

Is

ggplot( data = plot.df, aes( x = xvariable, y = yvariable ) ) +
  geom_line() +
  geom_point( data = plot.df[1:6,], aes( y = ypoints, x = xpoints ) )

what you are looking for?

Edit:

In my original answer I wrote that You cannot add multiple geometric objects of the same type to one ggplot. This is obviously wrong as the following example states:

dt <- data.frame( x = rnorm(1:10), y = rnorm(1:10) )
ggplot( mapping = aes( x = x, y = y ) ) +
  geom_point( data = dt[1:5,] ) +
  geom_point( data = dt[6:10,] )

However I have really difficulties to think of an example where this would be necessary. From my experience I would always presume that the reason for using two times the same geom in the same plot is a result of a bad data model.

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

Comments

1

Here's a dataset to work with.

plot.df <- data.frame(xvariable=1:6, yvariable=1:6+rnorm(6,0,0.3), xpoints=1:6+rnorm(6,0,0.1), ypoints=1:6+rnorm(6,0,0.1))

It IS possible to add multiple geometric objects of the same type to one ggplot. For example:

ggplot(data = plot.df, aes(x = xvariable)) + 
  geom_line(aes(y = yvariable)) +
  geom_point(aes(y=ypoints[1], x=xpoints[1])) +
  geom_point(aes(y=ypoints[2], x=xpoints[2])) +
  geom_point(aes(y=ypoints[3], x=xpoints[3])) +
  geom_point(aes(y=ypoints[4], x=xpoints[4])) +
  geom_point(aes(y=ypoints[5], x=xpoints[5])) +
  geom_point(aes(y=ypoints[6], x=xpoints[6]))

But that's a pain, and you're rightly seeking to avoid that sort of code replication. The answer depends on what you're looking for. Different formatting for each point? Try this:

ggplot(data = plot.df, aes(x = xvariable)) + 
  geom_line(aes(y = yvariable)) +
  geom_point(data=transform(plot.df, pointsID=as.factor(1:6)), 
             aes(y=ypoints, x=xpoints, color=pointsID))

You can alter the colors (or choices for other formatting parameters) through calls to scale_colour_discrete and related ggplot components.

PS - Your original strategy failed because ggplot waits until print time to evaluate arguments such as the i in xpoints[i]; even though you see 1 point, you're actually plotting 6 of the same point right on top of one another.

1 Comment

That's exactly what I was trying to do. I restructured my data already by realizing geom_point can take on whole dataframes of x,y coordinates based on the answer above. But checked this , and works as well.
1

While reworking the data structure to avoid loops like this is the better answer, sometimes you really need to evaluate the expression immediately instead of closing over a variable and evaluating the expression later. You can use ggplot2's aes_string() to do just that:

plot.test = ggplot(data = plot.df, aes(x = xvariable)) + 
  geom_line(aes(y = yvariable)) 

for (i in 1:6){
  plot.test = plot.test + geom_point(aes_string(y = ypoints[i], x = xpoints[i])) 
}

In this case you're effectively hardcoding the point values. That is, it's equivalent to:

  plot.test = plot.test + geom_point(aes(y = 2, x = 3))

You can also hardcode only the index, and still dynamically refer to whatever is in ypoints and xpoints at a later time:

  plot.test = plot.test + geom_point(aes_string(y = paste0("ypoints[", i, "]"), x = paste0("xpoints[", i, "]"))) 

This is ugly and unwieldy and a bit of a hack, but it works and is sometimes just what you need if you can't liberally reorganize the data structure for whatever reason.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.