4
votes

Is there any way to line up the points of a line plot with the bars of a bar graph using ggplot when they have the same x-axis? Here is the sample data I'm trying to do it with.

library(ggplot2)
library(gridExtra)

data=data.frame(x=rep(1:27, each=5), y = rep(1:5, times = 27))
yes <- ggplot(data, aes(x = x, y = y))
yes <- yes + geom_point() + geom_line()

other_data = data.frame(x = 1:27, y = 50:76  )

no <- ggplot(other_data, aes(x=x, y=y))
no <- no + geom_bar(stat = "identity")

grid.arrange(no, yes)

Here is the output:

enter image description here

The first point of the line plot is to the left of the first bar, and the last point of the line plot is to the right of the last bar.

Thank you for your time.

2
I'm not sure I understand what you want to do. The problem is that the bars have a width and the points don't. So the left edge of the first bar is at (about) x=0.5 and the right edge of the last bar at x=27.5. The first and last point are at x=1 and x=27. Aligning points and edges of bars thus seems quite unnatural, because this would mean that the two axes are scaled differently. Wouldn't it make more sense to have the centers of the bars aligned with the points?Stibu
How would I align the centers of the bars with the points?JakeC
See tracks package, here is an examplezx8754

2 Answers

2
votes

Extending @Stibu's post a little: To align the plots, use gtable (Or see answers to your earlier question)

library(ggplot2)
library(gtable)

data=data.frame(x=rep(1:27, each=5), y = rep(1:5, times = 27))
yes <- ggplot(data, aes(x = x, y = y))
yes <- yes + geom_point() + geom_line() + 
   scale_x_continuous(limits = c(0,28), expand = c(0,0))

other_data = data.frame(x = 1:27, y = 50:76  )

no <- ggplot(other_data, aes(x=x, y=y))
no <- no + geom_bar(stat = "identity") + 
   scale_x_continuous(limits = c(0,28), expand = c(0,0))

gYes = ggplotGrob(yes)   # get the ggplot grobs
gNo = ggplotGrob(no)

plot(rbind(gNo, gYes, size = "first"))   # Arrange and plot the grobs

enter image description here

Edit To change heights of plots:

g = rbind(gNo, gYes, size = "first")  # Combine the plots
panels <- g$layout$t[grepl("panel", g$layout$name)] # Get the positions for plot panels
g$heights[panels] <- unit(c(0.7, 0.3), "null") # Replace heights with your relative heights
plot(g)
1
votes

I can think of (at least) two ways to align the x-axes in the two plots:

  1. The two axis do not align because in the bar plot, the geoms cover the x-axis from 0.5 to 27.5, while in the other plot, the data only ranges from 1 to 27. The reason is that the bars have a width and the points don't. You can force the axex to align by explicitly specifying an x-axis range. Using the definitions from your plot, this can be achieved by

    yes <- yes + scale_x_continuous(limits=c(0,28))
    no <- no + scale_x_continuous(limits=c(0,28))
    grid.arrange(no, yes)
    

    limits sets the range of the x-axis. Note, though, that the alginment is still not quite perfect. The y-axis labels take up a little more space in the upper plot, because the numbers have two digits. The plot looks as follows: enter image description here

  2. The other solution is a bit more complicated but it has the advantage that the x-axis is drawn only once and that ggplot makes sure that the alignment is perfect. It makes use of faceting and the trick described in this answer. First, the data must be combined into a single data frame by

    all <- rbind(data.frame(other_data,type="other"),data.frame(data,type="data"))
    

    and then the plot can be created as follows:

    ggplot(all,aes(x=x,y=y)) + facet_grid(type~.,scales = "free_y") +
       geom_bar(data=subset(all,type=="other"),stat="identity") +
       geom_point(data=subset(all,type=="data")) +
       geom_line(data=subset(all,type=="data"))
    

    The trick is to let the facets be constructed by the variable type which was used before to label the two data sets. But then each geom only gets the subset of the data that should be drawn with that specific geom. In facet_grid, I also used scales = "free_y" because the two y-axes should be independent. This plot looks as follows:

enter image description here

You can change the labels of the facets by giving other names when you define the data frame all. If you want to remove them alltogether, then add the following to your plot:

+ theme(strip.background = element_blank(), strip.text = element_blank())