Datoraki
Datoraki

Reputation: 1223

ggplot2: adding lines in a loop and retaining colour mappings

When running the following two pieces of code, I unexpectedly get different results. I need to add lines in a loop as in EX2, but all lines end up having the same colour. Why is this?

EX1

economics2 <- economics
economics2$unemploy <- economics$unemploy + 1000
economics3 <- economics
economics3$unemploy <- economics$unemploy + 2000
economics4 <- economics
economics4$unemploy <- economics$unemploy + 3000
b <- ggplot() +
 geom_line(aes(x = date, y = unemploy, colour = as.character(1)), data=economics2) +
 geom_line(aes(x = date, y = unemploy, colour = as.character(2)), data=economics3) +
 geom_line(aes(x = date, y = unemploy, colour = as.character(3)), data=economics4)
print(b)

EX1

EX2

#economics2, economics3, economics4 are reused from EX1.
b <- ggplot()
econ <- list(economics2, economics3, economics4)
for(i in 1:3){
  b <- b + geom_line(aes(x = date, y = unemploy, colour = as.character(i)), data=econ[[i]])
}
print(b)

EX2

Upvotes: 2

Views: 8592

Answers (1)

jlhoward
jlhoward

Reputation: 59355

This is not a good way to use ggplot. Try this way:

econ <- list(e1=economics2, e2=economics3, e3=economics4)
df   <- cbind(cat=rep(names(econ),sapply(econ,nrow)),do.call(rbind,econ))
ggplot(df, aes(date,unemploy, color=cat)) + geom_line()

This puts your three versions of economics into a single data.frame, in long format (all the data in 1 column, with a second column, cat in this example, identifying the source). Once you've done that, ggplot takes care of everything else. No loops.

The specific reason your loop failed, as pointed out in the comment, is that using aes(...) stores the expression in the ggplot object, and that expression is evaluated when you call print(...). At that point i is 3.

Note that this does not apply to the data=... argument, so you could have done something like this:

b=ggplot()
for(i in 1:3){
  b <- b + geom_line(aes(x=date,y=unemploy,colour=cat), 
                     data=cbind(cat=as.character(i),econ[[i]]))
}
print(b)

But, this is still the wrong way to use ggplot.

Upvotes: 4

Related Questions