3

I'm trying to draw a series of boxes in ggplot2 using a loop. Below, I have included a toy example.

# Load necessary library
library(ggplot2)

# Height of rectangle
box.size <- 0.5

# Colours for rectangles
my.cols <- c("red", "blue", "purple", "yellow", "green")

# Initialise plot & set limits
p <- ggplot() + xlim(0, 1) + ylim(0, 2.5)

# Loop through and draw boxes
for(i in 1:5){
  # Draw boxes
  p <- p + geom_rect(aes(xmin = 0, xmax = 1, ymin = (i - 1) * box.size, ymax = i * box.size), 
                 fill = my.cols[i])

  # Check that the loop is working
  print(i) 
}

# Plot graph
print(p)

This code only plots the final rectangle, but I can't figure out what I am doing wrong. The loop is running correctly because I included a print statement to check. Can someone point out my error and offer a solution, please?

3
  • ggplot is designed for plotting data. I'd recommend you construct a data frame (in a similar loop, if you want) and then plot that. As-is, you're trying to use a screwdriver as a hammer. Commented Jan 25, 2017 at 20:38
  • Okay, understood. Thanks for the helpful reply. Out of curiosity, though: why does the code fail? Commented Jan 26, 2017 at 0:14
  • I'm not sure exactly. My ggplot is strongly designed around the data frame. You almost certainly shouldn't be using aes() without a data frame, but even without that your code doesn't work. And the for loop has nothing to do with it - if you write out the first couple iterations by hand, the first layer works as expected and the second doesn't. Commented Jan 26, 2017 at 0:33

2 Answers 2

4

I agree with Gregor. Just make a function, loop, or statement to construct the underlying data, then plot it with ggplot2.

library(ggplot2)

box.size <- 0.5

df <- data.frame(xmin = rep(0, 5),
           xmax = rep(1,5),
           ymin = (seq(1:5)-1) * box.size,
           ymax = seq(1:5) * box.size,
           fill = c("red", "blue", "purple", "yellow", "green"))

 ggplot(df) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, fill = fill)) +
  scale_fill_identity()

enter image description here

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

Comments

0

As noted by Gregor, ggplot is not meant to be used with loops. You need to set up your coordinates into a dataframe first:

library(dplyr)
library(ggplot2)
mydf <- data.frame(my.cols, tmp = rep(box.size, 5), i = 1:5)
mydf <- mutate(mydf, ymin = (i - 1) * tmp, ymax = tmp * i)
mydf <- select(mydf, -tmp, -i)

ggplot(mydf) + xlim(0,1) + ylim(0, 2.5) + geom_rect(aes(xmin = 0, xmax = 1, ymin = ymin, ymax = ymax), fill = my.cols)

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.