2

Using graphics it is fairly easy to plot 2 graphs with the same x-axis playing with mar I would like to reproduce with ggplot2, but it seems difficult.

What I want: I would like to plot a geom_line (several lines), and directly bellow (so no axis/ticks/...) a geom_bar (with same group) that would display the axis with axis/grid perfectly aligned

Data:

library(data.table)
DT <- data.table( y = runif(400, max = 2), 
                      grp = sample(c('M', 'F'),size = 400, replace = T), 
                      x = rep(as.Date(1:10,origin='2011-01-01'), each = 40)
    )
TS <- DT[,.(y=sum(y[1L])),.(x,grp)][,y:=cumsum(y),.(grp)]
#make a "hole" so it is not too easy
BC <- DT[,.(y=uniqueN(y)),.(x,grp)][x!='2011-01-05']
#join so the table is the same
plotData <- merge(TS,BC,by=c('x','grp'),all=T,suffixes=c('_ts','_bc'))

Looks like:

             x grp      y_ts y_bc
 1: 2011-01-02   F  1.196320   20
 2: 2011-01-02   M  1.603109   20
 3: 2011-01-03   F  2.549560   26
 4: 2011-01-03   M  3.433326   14
 5: 2011-01-04   F  2.755620   22
 6: 2011-01-04   M  4.819931   18
 7: 2011-01-05   F  3.492297   NA
 8: 2011-01-05   M  6.431233   NA
 9: 2011-01-06   F  4.236778   18
10: 2011-01-06   M  7.008271   22
11: 2011-01-07   F  5.207380   18
12: 2011-01-07   M  8.636382   22
13: 2011-01-08   F  5.441116   19
14: 2011-01-08   M  9.462970   21
...

With grid.arrange:

library(ggplot2)
library(gridExtra)
# first graph
ts <- ggplot(plotData) + aes(x=x,y=y_ts,color=grp) + geom_line() 
#remove axis etc...
ts <- ts + theme(axis.ticks.x = element_blank(), axis.text.x = element_blank(), axis.title.x = element_blank())
# second graph
bc <- ggplot(plotData) + aes(x=x,y=y_bc,group=interaction(x,grp),fill=grp) 
bc <- bc + geom_bar(position='dodge',stat='identity')
#arrange
grid.arrange(ts, bc , ncol=1,  layout_matrix = matrix(c(1,2),nrow=2), heights=c(2,1))

enter image description here

But clearly BOTH plots and grid are still miss-aligned

with gtable: only grid is wrong

require(ggplot2)
require(gtable)
#Extract Grobs
g1<-ggplotGrob(ts)
g2<-ggplotGrob(bc)
#Bind the tables
g<-gtable:::rbind_gtable(g1, g2, 'first')
#Remove a row between the plots
g <- gtable_add_rows(g, unit(0,"line"), pos=nrow(g1))
#draw
grid.newpage()
grid.draw(g)

enter image description here

statquant
  • 13,672
  • 21
  • 91
  • 162
  • 2
    Possible duplicate of [left align two graph edges (ggplot)](http://stackoverflow.com/questions/13294952/left-align-two-graph-edges-ggplot) or [Align plot areas in ggplot](http://stackoverflow.com/questions/13656642/align-plot-areas-in-ggplot?lq=1). – Henrik Feb 21 '16 at 14:05

1 Answers1

2

This will do it:

ts <- ts + xlim(range(plotData[, x]) + c(-.5, .5)) +
                      theme(plot.margin=unit(c(0,0,0,0),'lines'))
bc <- bc + xlim(range(plotData[, x]) + c(-.5, .5)) +
                      theme(plot.margin=unit(c(-.5,0,0,0),'lines'))
grobs <- lapply(list(ts,bc), FUN=ggplot2::ggplotGrob)
max_widths <- do.call(grid::unit.pmax, lapply(grobs,  function(x) { x$widths }))
num_plots <- length(grobs)
for (i in 1:num_plots) {
      grobs[[i]]$widths <- max_widths
}
grid.arrange(grobs=grobs , ncol=1, layout_matrix = matrix(c(1,2),nrow=2), heights=c(2,1))   

enter image description here

statquant
  • 13,672
  • 21
  • 91
  • 162