Josh
Josh

Reputation: 23

Overlaying a Bar chart with multiple bars with a line graph with ggplot2 in R

I am trying to create a specific graph using ggplot2, this is my dataset.

df.1 <- data.frame(
Month = c("Dec-17", "Jan-18", "Feb-18", "Mar-18", "Apr-18", "May-18"), 
Total_1 = c(25, 14, 8, 16, 137, 170), 
Total_2 = c(3, 2, 3, 2, 18, 27), 
Total_3 = c(5, 4, 3, 2, 16, 54)
)

I want Total_2 and Total_3 to be bars and Total_1 to be a line chart all on the same graph. I have got this far with my coding:

df.1 <- melt(df.1,id.vars = "Month")
#reorder the month column so it isn't alphabetical
df.1$Month <- factor(df.1$Month, levels(df.1$Month)[c(2,4,3,5,1,6)])
#partition my data into the 2 different graphs I need
df.1.1 <- df.1[7:18,]
df.1.2 <- df.1[1:6,]

ggplot(data = df.1.1, aes(x = df.1.1$Month, y = df.1.1$value, fill = df.1.1$variable)) + 
  geom_bar(position = position_dodge(),stat = 'identity') +
  geom_line(data = df.1.2, aes(x=df.1.2$id, y=df.1.2$value, group=1))

This then gives me the error:

Error: Aesthetics must be either length 1 or the same as the data (6): x, y, fill

The first half of my ggplot code, namely:

    ggplot(data = df.1.1, aes(x = df.1.1$Month, y = df.1.1$value, fill = df.1.1$variable)) + 
  geom_bar(position = position_dodge(),stat = 'identity')

Which gives me the following chart: enter image description here

I just need the line part to be on top of this. I can generate the line graph on its own using this bit of code:

ggplot(data = df.1.2, aes(x = df.1.2$Month, y = df.1.2$value, group = 1)) + 
      geom_line()

Which looks like so: enter image description here

Any help to getting this to work is greatly appreciated, and if you need any more information don't be afraid to ask.

Thanks!

Upvotes: 1

Views: 3016

Answers (1)

StephenK
StephenK

Reputation: 695

The main problem here is the fill in the ggplot call. Because you have it in ggplot(aes()), it is propagating to both geom_bar and geom_line. If you just set fill = variable inside ggplot(aes()), you wouldn't get the error, but you would have an Total_1 in the legend, which is not what I think you want.

You also don't need to use the df.1.1$ and df.1.2$ inside aes(). You want to put your data in the data argument and then the variables in aes() without calling the data frame again.

Here is a solution.

ggplot(data = df.1.1, aes(x = Month, y = value)) + 
  geom_bar(aes(fill = variable), position = position_dodge(),stat = 'identity') +
  geom_line(data = df.1.2, aes(x=Month, y=value, group=1))

One other note is that you can use geom_col instead of geom_bar with stat='identity'.

ggplot(data = df.1.1, aes(x = Month, y = value)) + 
  geom_col(aes(fill = variable), position = position_dodge()) +
  geom_line(data = df.1.2, aes(x=Month, y=value, group=1))

Upvotes: 1

Related Questions