It doesn't matter if they are in a loop, you just need to associate each level with a color. In your case:
colourList <- c(bird_one = "red", bird_two = "blue", bird_three = "green")
In a simple example:
#Make some data dat <- data.frame(location = rep(1:4, c(3,2,2,3)), val = rnorm(10), depth.from = sample(1:5, 10, replace = TRUE), depth.to = sample(6:10, 10, replace = TRUE), type = factor(LETTERS[c(1:3, 1,3,1,3,1:3)])) #Associate levels with colours colourList <- c(A = "red", B = "blue", C = "green") p <- list() for(i in 1:4) { d <- dat[dat$location == i,] p[[i]] <- ggplot(data = d, aes (y=val, x=depth.from))+ layer(geom = "point", size = 2) + geom_rect(aes(xmin=depth.to, xmax=depth.from, ymin=0, ymax=100, fill = type), linetype =0, alpha=0.3) + #This is where the assignment works scale_fill_manual(values=colourList) } grid.arrange(p[[1]], p[[2]])
You can see that the C level in both graphs is green.
In response to @BrodieG, here is a way to set colors semi-automatically. It creates a named vector using type levels and color values ββfrom the RColorBrewer package. This could be pretty easy to design for inclusion in a function:
library(RColorBrewer) colourList <- setNames(brewer.pal(length(levels(dat$type)), "Set1"), levels(dat$type))
As @hadley points out, in this case itβs even more straightforward to set scale limits, although in my typical use, I find it more useful to set up an object such as colourList , which can be used on multiple graphs simply by setting values . The limits setting also supports legend levels, which may or may not be what you need:
scale_fill_brewer(limits = levels(dat$type), palette = "Set1")

As @hadley points out, in this case itβs even more straightforward to set scale limits, although in my typical use, I find it more useful to set up an object such as colourList , which can be used on multiple graphs simply by setting values . The limits setting also supports legend levels, which may or may not be what you need:
scale_fill_brewer(limits = levels(dat$type), palette = "Set1")
