Hi:
The major problem with your approach is that you didn't realize the impact of the legend in your first plot on the alignment. The easy way out would be to reposition the legend so that it was either inside the plot region, on top or on the bottom before you applied the gtable magic. If you do that, then the remainder of what you tried should work.
Another approach, which might be more visually appealing in some cases, is to extract the legend from the first plot and reposition it on the graphics page. The following is an adaptation of an exchange between Brian Zen and me in this forum about 10 days ago (thread title: move_facet_strip_y). Brian's use case was to align two concurrent time series of different variables stacked on top of one another. My response showed how this could be done somewhat more generally (and pedantically) and that's what I'll show here. The packages grid, gridExtra and ggplot2 need to be loaded. Given your plot objects p1 and p2:
Step 1: Extract the legend from the first plot.
Step 2: Redo the first plot with the legend removed - call it p1a.
Step 3: Create gtables of p1a and p2
Step 4: Edit the gtable objects to align the left margins of the plot regions.
Step 5: Create a layout matrix to position the grobs.
Step 6: Render the graphic using grid.arrange().
To extract the legend, we'll use the following function from
# ----------------
g_legend<-function(a.gplot){
tmp <- ggplot_gtable(ggplot_build(a.gplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
legend
}
# Extract the legend from p1
leg <- g_legend(p1)
# Redo p1 without the legend
p1a <- p1 + theme(legend.position = "none")
# Create gtable objects of p1a and p2
gp1 <- ggplot_gtable(ggplot_build(p1a))
gp2 <- ggplot_gtable(ggplot_build(p2))
# Edit the left margins of the two gtable objects
# in order to align them
maxwidth <- grid::unit.pmax(gp1$widths[2:3], gp2$widths[2:3])
gp1$widths[2:3] <- as.list(maxwidth)
gp2$widths[2:3] <- as.list(maxwidth)
# Create a layout matrix for positioning the grobs
# This one uses 80% of each row for the plot, 20% for the margin
lay <- rbind(c(1, 1, 1, 1, 3), c(2, 2, 2, 2, 3))
# Render the plot
grid.arrange(gp1, gp2, leg, layout_matrix = lay)
#--------------
Side comment: Please don't post code like this: 'rm(list=ls())'. At the very least, comment it out. Imagine you were trying to help someone in the middle of an extensive R session and you didn't notice this line in a code block you copied and pasted into your session. How would you feel if your entire global environment were wiped out this way? I've seen several folks on R-help who were victimized by this practice over the years and I can assure you they were not thrilled.
Dennis