user3390169
user3390169

Reputation: 1045

R ggplot2: Line overlayed on Bar Graph (from separate data frames)

I have a bar graph coming from one set of monthly data and I want to overlay on it data from another set of monthly data in the form of a line. Here is a simplified example (in my data the second data set is not a simple manipulation of the first):

library(reshape2)
library(ggplot2)

test<-abs(rnorm(12)*1000)
test<-rbind(test, test+500)
colnames(test)<-month.abb[seq(1:12)]
rownames(test)<-c("first", "second")
otherTest<-apply(test, 2, mean)
test<-melt(test)
otherTest<-as.data.frame(otherTest)

p<-ggplot(test, aes(x=Var2, y=value,  fill=Var1, order=-as.numeric(Var2))) + geom_bar(stat="identity")+
    theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(), 
    panel.grid.minor = element_blank(), axis.line = element_line(colour = "black")) +
    ggtitle("Test Graph") +
    scale_fill_manual(values = c(rgb(1,1,1), rgb(.9,0,0))) + 
    guides(fill=FALSE) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) 

works great to get the bar graph: enter image description here

but I have tried multiple iterations to get the line on there and can't figure it out (like this):

p + geom_line(data=otherTest,size=1, color=rgb(0,.5,0)

Also, if anybody knows how I can make the bars in front of each other so that all you see is a red bar of height 500, I would appreciate any suggestions. I know I can just take the difference between the two lines of the matrix and keep it as a stacked bar but I thought there might be an easy way to put both bars on the x-axis, white in front of red. Thanks!

Upvotes: 0

Views: 1653

Answers (1)

Simon Jackson
Simon Jackson

Reputation: 3174

You have a few problems to deal with here.

Directly answering your question, if you don't provide a mapping via aes(...) in a geom call (like your geom_line...), then the mapping will come from ggplot(). Your ggplot() specifies x=Var2, y=value, fill=Var1.... All of these variable names must exist in your data frame otherTest for this to work, and they don't right now.

So, you either need to ensure that these variable names exist in otherTest, or specify mapping separately in geom_line. You might want to read up about how these layering options work. E.g., here's a post of mine that goes into some detail.

If you go for the first option, some other problems to think about:

  • is Var2 a factor with the same levels in both data frames? It probably should be.
  • to use geom_line as you are, you might need to add group = 1. See here.

Some others too, but here's a brief example of what you might do:

library(reshape2)
library(ggplot2)

test <- abs(rnorm(12)*1000)
test <- rbind(test, test+500)
colnames(test) <- month.abb[seq(1:12)]
rownames(test) <- c("first", "second")
otherTest <- apply(test, 2, mean)
test <- melt(test)

otherTest <- data.frame(
  Var2 = names(otherTest),
  value = otherTest
)

otherTest$Var2 = factor(otherTest$Var2, levels = levels(test$Var2))

ggplot(test, aes(x = Var2, y = value, group = 1)) +
  geom_bar(aes(fill = Var1), stat="identity") +
  geom_line(data = otherTest)

Upvotes: 1

Related Questions