1
votes

I want to combine a line and a bar chart with three different variables using ggplot. The bar chart should have the values on top and should be filled with the same colours as the lines in the chart above. Here is my code

# First some data generation
df.x = data.frame(date = Sys.Date()-20:1,
                  value = c(1:20),
                  variable = "line",
                  object = "x")

df.y = data.frame(date = Sys.Date()-20:1,
                  value = c(1:20)*2,
                  variable = "line",
                  object = "y")

df.z = data.frame(date = Sys.Date()-20:1,
                  value = c(1:20)*3,
                  variable = "line",
                  object = "z")

df.y.bar = data.frame(date = Sys.Date()-10,
                  value = 30,
                  variable = "bar",
                  object = "y")

df.x.bar = data.frame(date = Sys.Date()-10,
                      value = 40,
                      variable = "bar",
                      object = "x")

df.z.bar = data.frame(date = Sys.Date()-10,
                      value = 50,
                      variable = "bar",
                      object = "z")

df = rbind(df.x, df.y,df.z, df.x.bar, df.y.bar,df.z.bar)

my.cols = c("blue", "green", "yellow")

# Pass everything to ggplot
ggplot(df, aes_string(x = "date", y = "value", fill="variable")) +  
  facet_grid(variable~., scales="free_y") + 
  geom_line(data = subset(df, variable == "line"), aes(colour = factor(object)), size = 1, show_guide = FALSE, stat="identity") +
  geom_bar(data = subset(df, variable == "bar"), aes(colour = factor(object)), show_guide = TRUE, stat="identity", position = "dodge") +
  geom_text(data = subset(df, variable == "bar"), aes(y=value+0.7 * sign(value), ymax=value, label=round(value, 2)), position = position_dodge(width = 0.9), size=3) + 
  scale_colour_manual(values = my.cols)

The resulting plot is not exactly what I wanted. I used position_dodge(width = 0.9) but the text over the bars does not move. Irretatingly this does not happen when I only chose two variable (e.g. x and y) to be included in the data frame. The desired result should look like this:

enter image description here

Thanks a lot for your help!

1
Was my answer helpful?erc
Hi beetroot. It works with your data. I tried it on my data set and the colouring of the bars worked just fine. Unfortunately the text above the bars still doesn't move, even if i apply the group Argument...Pat
Weird, can you post some data and the code to reproduce the text problem?erc
It will probably exceed the simplicity of the above example by far. Should I post the code anyway?Pat

1 Answers

2
votes

You can fill the bars by choosing fill = factor(object) and adding scale_fill_manual(values = my.cols). In order to have only one legend I think removing fill="variable" from aes_string did the trick in combination with scale_fill_manual. And for dodging the text you need to add a group argument and position = position_dodge(width=1)

ggplot(df, aes_string(x = "date", y = "value")) +  
          facet_grid(variable~., scales="free_y") + 
          geom_line(data = subset(df, variable == "line"), aes(colour = factor(object)), size = 1, show_guide = FALSE, stat="identity") +
          geom_bar(data = subset(df, variable == "bar"), aes(fill = factor(object)), show_guide = TRUE, stat="identity", position = "dodge") +
          geom_text(data =subset(df, variable == "bar"), aes(x=date, y=(value+0.7) * sign(value), ymax=value, label=round(value, 2), group=object), position = position_dodge(width=1), size=3) +
          scale_colour_manual(values = my.cols) +
          scale_fill_manual(values = my.cols)

enter image description here