10

I have generated a figure that combines ggplot and base graphics:

t <- c(1:(24*14)) 
P <- 24
A <- 10 
y <- A*sin(2*pi*t/P)+20 
#*****************************************************************************
par(mfrow = c(2,1))
plot(y,type = "l",xlab = "Time (hours)",ylab = "Amplitude")
aa <- par("mai")
plot.new()

require(gridBase)
vps <- baseViewports()
pushViewport(vps$figure)
pushViewport(plotViewport(margins = aa)) ## I use 'aa' to set the margins 
#*******************************************************************************
require(ggplot2)
acz <- acf(y, plot = FALSE)
acd <- data.frame(Lag = acz$lag, ACF = acz$acf)
p <- ggplot(acd, aes(Lag, ACF)) + geom_area(fill = "grey") +
  geom_hline(yintercept = c(0.05, -0.05), linetype = "dashed") +
  theme_bw()
grid.draw(ggplotGrob(p)) ## draw the figure

I use the plotViewport command and set the dimensions of the panel according to the dimensions of the first panel, obtained by par("mai"). The figure attached shows the outcome. enter image description here However, the dimensions of both panels do not match, i.e. the second panel seems to be slightly wider than the first. How can I overcome this without having to manually set the margins with

pushViewport(plotViewport(c(4,1.2,0,1.2)))
baptiste
  • 75,767
  • 19
  • 198
  • 294
KatyB
  • 3,920
  • 7
  • 42
  • 72
  • 1
    This is hard enough using only a single graphics system, let alone two. There used to be a package `ggextra` with a function `align.plots` but this has been deprecated. See https://groups.google.com/forum/?fromgroups=#!topic/ggplot2-dev/4dKg-qA7eZE – Andrie Jan 09 '13 at 09:01

2 Answers2

6

This should give you some hints:

screenshot

library(grid)
library(ggplot2)
require(gridBase)

par(mfrow = c(2,1))
plot(1:10)
a <- par("mai")
plot.new()
vps <- baseViewports()
pushViewport(vps$figure)

p = qplot(1:10, 1:10) + theme_bw() 
g <- ggplotGrob(p)

lw = unit(a[2], "inch") - sum(g$widths[1:3]) 

g$widths[[2]] <- as.list(lw + g$widths[[2]])
g$widths[[4]] <- as.list(unit(1, "npc") - unit(a[2] + a[4], "inch"))
g$widths[[5]] <- unit(a[4], "inch")
grid.draw(g)

# draw a shaded vertical band to test the alignment
grid.rect(unit(a[2], "inch"), unit(0, "inch"), 
          unit(1,"npc") - unit(a[2] + a[4], "inch"), 
          unit(2,"npc"),
          gp=gpar(lty=2, fill="red", alpha=0.1), hjust=0, vjust=0)

upViewport()

but, really, why would you not do everything in ggplot2?

baptiste
  • 75,767
  • 19
  • 198
  • 294
  • thanks for this. The main reason for wanting to combine ggplot2 and base graphics was the thought that some plots based on base graphics are not implemented in grid (e.g. biplot). – KatyB Jan 10 '13 at 14:16
3

Th main idea is to push 2 viewports of baseviewports to get the dimensions of the plot panel. The solution is not general.

First I plot my basic plot

t <- c(1:(24*14)) 
P <- 24
A <- 10 
y <- A*sin(2*pi*t/P)+20 
#*****************************************************************************
par(mfrow = c(2,1))
plot(t,y,type = "l",xlab = "Time (hours)",ylab = "Amplitude")
plot.new()

Second I get the dimensions of the plot panel. vpp will be used just for dimensions of ggplot grobs(similar to the idea of baptiste above)

require(gridBase)
vps <- baseViewports()
vpp <- pushViewport(vps$figure,vps$plot) ## here I add a new viewport
vpp <- current.viewport()
upViewport(2)

ggplot2 plot savec as a grob table:

require(ggplot2)
p <- ggplot(acd, aes(Lag, ACF)) + geom_area(fill = "grey") +
  geom_hline(yintercept = c(0.05, -0.05), linetype = "dashed") +
  theme_bw()
data <- ggplot_build(p)
gtable <- ggplot_gtable(data)

I change the dimensions of the grobs. (Here why the solution is not general)

gtable$heights[[2]] <- vpp$height
gtable$heights[[4]] <- vpp$height
gtable$widths[[4]]  <- vpp$width

I plot

grid.draw(gtable)

enter image description here

agstudy
  • 119,832
  • 17
  • 199
  • 261
  • I believe upon close inspection the two won't be exactly aligned, as ggplot will center its plot on the viewport and the left/right margins may differ. – baptiste Jan 09 '13 at 18:42
  • @baptiste You're right. I am personally not satisfied of my solution. When I test it with other mar, e.g mar(2,1) and mar(2,2) and I had to modify the grobs dimensions. But with my solution the **vpp** has the right dimensions of the plot( I tested it with grid.rect), maybe you can use it to modify ggplot2 grobs. – agstudy Jan 09 '13 at 18:48