Albert Zhao
Albert Zhao

Reputation: 106

R: How to save base plot to a grid object, except from grid.echo()

Background: I used a wrapped plot function from the package MatchIt (a package for propensity scoring matching), and find difficulties in putting the graphs together on one page.

My solution: To convert the plots to grid objects first (using grid.echo and grid.grab from gridGraphics package), and then use grid.arrange from gridExtra package to arrange them.

The problem: when using grid.echo, an error occurs: "Error in unit(x, default.units) : 'x' and 'units' must have length > 0".

I figured out that this comes from the fact that part of the graph has all FALSE values. Instead of trying to hack the grid.echo function or the plot function, I would like to ask if there is another way of saving the base plot as grobs objects?

Here is a minimal reproducible example:

### Generate data and the model
set.seed(10)
df <- data.frame(y=sample(c(0,1),20,replace=TRUE),x1=rnorm(20),x2=1:20)
library(MatchIt)
m.out <- matchit(y~x1+x2,data=df,method='nearest',replace=TRUE,ratio=2,discard="treat") 
### This one is OK because "discard" is set, so that the plot has none empty values in all parts    
m.out_none <- matchit(y~x1+x2,data=df,method='nearest',replace=TRUE,ratio=2,discard="none") 
### This one is NOT OK because "discard" is not set, so part of the plot is empty.

### function to convert base plot to grid objects
library(gridGraphics)
grab_grob <- function(){
    grid.echo()
    grid.grab()
}

plot(m.out_none,interactive=FALSE,type='jitter')
p1 <- grab_grob() ### Error here
plot(m.out,interactive=FALSE,type='jitter')
p2 <- grab_grob() ### No errors

Upvotes: 1

Views: 1149

Answers (1)

Len Greski
Len Greski

Reputation: 10855

The two charts can be combined into a single output file with the par() function without having to convert the graphics to other object types. In this scenario we'll use par(mfrow=c(1,2)) to instruct base R graphics to write two plots in one row. Using the example code from the original post, we generate the graphs as follows.

set.seed(10)
df <- data.frame(y=sample(c(0,1),20,replace=TRUE),x1=rnorm(20),x2=1:20)
library(MatchIt)
m.out <- matchit(y~x1+x2,data=df,method='nearest',replace=TRUE,ratio=2,discard="treat")     
m.out_none <- matchit(y~x1+x2,data=df,method='nearest',replace=TRUE,ratio=2,discard="none") 
# configure an output file to which the charts will be written
thePngFile <- png(file="matchit.png",width=960,height=480,units = "px")
# configure output file with 1 row and 2 columns
par(mfrow=c(1,2))
plot(m.out_none,interactive=FALSE,type='jitter')
title(sub="out_none")
plot(m.out,interactive=FALSE,type='jitter')
title(sub="out")
dev.off()

The code produces the following output file.

enter image description here

Note that if the charts are specified in this manner as part of an R Markdown document, no extra output file is necessary. R will render the two charts in one figure within the output document.

Upvotes: 1

Related Questions