How to export arrangeGrob output via win.metafile() - r

I need to save plots from R as EMF format (windows metafile format) because this makes the chart look good on screen and paper in Microsoft Word. No other option (PNG, postscript etc) works well on both. The PNG device produces poor res plots. Tinkering with res parameters blows up the graph elements and I can't find anything that clearly explains how to mitigate this. Using postscript print output is pretty good. However, Word's EPS filters are busted so that I can't see the EPS file on screen. I need something that works well on screen and on paper. win.metafile is only thing that does both.
Here's the twist. I am using gridExtra to customise the layout of my plots. From what I gather, this means that I am writing multiple plots onto one device (which I then want to export to EMF). But I know that win.metafile only allows one plot per file. From ?win.metafile:
For win.metafile only one plot is allowed per file
So the following shouldn't work:
library(ggplot2)
library(gridExtra)
# g_legend pinched from Hadley:
# https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
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]]
return(legend)
}
win.metafile(file='test.emf', width=6, height=4)
p <- ggplot(mtcars, aes(x=cyl, y=mpg, colour=factor(gear)))
pl <- p + geom_point()
legend <- g_legend(pl)
lwidth <- sum(legend$width)
pp <- arrangeGrob(pl + theme(legend.position="none"), legend)
pp
dev.off()
In fact I get the following error message:
Error in grid.newpage() : metafile 'test.emf' could not be created
Ok. So here's my question: how can I trick win.metafile to see only one plot from the arrangeGrob output? Can I stuff its output into something and get one plot out? It must be possible because if I use RStudio's export function, I get an excellent looking chart on screen and paper. But I want to codify this so I don't have to manually export the files.
I've scoured the web and haven't been able to find anything that addresses this. Help would be greatly appreciated!

I tried this just now using the devEMF package, and though it throws a warning it looks like the picture that you've created here.
You just need to install.packages('devEMF') and then:
require(devEMF)
emf('imPic.emf')
print(pp)
dev.off()

Related

Force R to show plot before input in Colab

I'd like to display a plot and then have the user give some input, but the plot always appears after the input line. A simple example is:
plot( 1:10 )
ans <- readline("What is your favorite number?")
which gives the prompt first and then does the plot. The end goal will then be to do this in a for loop, where each iteration I present a plot and then ask the user for feedback about the plot.
This is in Colab and I'd like to stay working in Colab as this is an application for students and I want something they can run easily.
I've tried various things including Sys.sleep(0) and flush.console() but without any luck.
Edit My MWE above isn't actually representative of my code. A better example is the following:
par(mfrow=c(1,2))
plot(1:10)
plot(1:10)
print('Hello')
you could use plot.new():
This function (frame is an alias for plot.new) causes the completion of plotting in the current plot
plot( 1:10 )
plot.new()
ans <- readline("What is your favorite number?")

Creating Multiple Plots in Multiple files with ggplot2 in R

Having an unusual problem with creating multiple files in R with ggplot2.
I've got multiple plots to create for multiple people, so I'm creating all the plots for each person in a pdf. So it goes something like this...
for(i in 1:10)
{
pdf(paste("person",i,".pdf",sep=""))
ggplot2(...)+.........
ggplot2(...)+.........
ggplot2(...)+.........
ggplot2(...)+.........
dev.off()
}
I've verified that all the code to create the plots is working and that creating a single pdf works, no problems there. The problem arises when I try to run the loop, it creates the files, but they're blank. I've tried everything I can think of and can't seem to find any information about this. I've tried in RStudio (Windows) and command line (ubuntu), both create the same issue.
Any insight or an alternative would be appreciated, thanks
You need to use print for each plot want you output into a pdf.
library(ggplot2)
dat = data.frame(x1=rnorm(10), x2=rnorm(10))
for(i in 1:2){
pdf(paste("person",i,".pdf",sep=""))
p1 = ggplot(dat, aes(x=x1)) + geom_histogram()
p2 = ggplot(dat, aes(x=x2)) + geom_histogram()
print(p1)
print(p2)
dev.off()
}

ggplot2 plot fill page in landscape (pdf)

I'm trying to render a plot to a PDF using the following approach:
pdf('~/Desktop/test.pdf', bg = "white", paper="USr")
p <- ggplot(df, aes(something)) + geom_bar();
print(p)
# I'm actually printing a bunch of graphs to the PDF
dev.off()
The "USr" in the PDF function is setting up the PDF to print in landscape mode. The plot is produced and is centered on the page but there is a large right/left margin and the plot isn't scaling out to take up the full 11" available to it.
I've tried some tweaks to the pdf(...) command and to the ggplot itself. Is there a solution this way or do I need to use a dedicated reporting/pdf package like sweave or knitr?
See this discussion; bottom-line is you probably want to use paper=special and set width and height explicitly.
Edit:
Here's a lazy trick to use ggsave with multiple pages,
library(ggplot2)
plots = replicate(8, qplot(1,1), simplify=FALSE)
library(gridExtra)
p <- do.call(marrangeGrob, c(plots,ncol=1,nrow=1))
ggsave("multipage.pdf", p, width=11, height=8.5)
(but otherwise, pdf(...) followed by a for loop is just fine and sometimes clearer)

Plot in nowhere

I am using the function plotMDS() of package limma that makes a plot by the simple plot() format of R, and also returns the position of the points on the plot as output. I want to use the output of plotMDS() to produce my own beautiful plot.
Is there any way to run plotMDS() without having it's plot really generated? The reason I ask so is that I have already casted the output to a PDF file and I don't want the original plot of the plotMDS() to be there!
Thanks #BenBolker, it can be done like this:
pdf("Some file")
...
dev.new() # Putting new plots to nowhere
mds <- plotMDS(data)
dev.off() # Restoring new plots to the PDF file
plot(...) # Making the desired plot using mds
...
dev.off() # Closing PDF file
Looking at your answer it seems like this might be a reasonable alternative:
mds <- plotMDS(data)
pdf("Some file")
...
plot(...) # Making the desired plot using mds
...
dev.off() # Closing PDF file
I don't know exactly what you're doing but if you're interested in reproducible documents then you could also use the knitr package to create your output. It would be very easy to suppress a single plot and then plot later using knitr.

Save ggplot within a function

I'm trying to save a ggplot within a function using graphics devices. But I found the code produces empty graphs. Below is a very very simple example.
library(ggplot2)
ff <- function(){
jpeg("a.jpg")
qplot(1:20, 1:20)
dev.off()
}
ff()
If I only run the content of the function, everything is fine. I know that using ggsave() will do the thing that I want, but I am just wondering why jpeg() plus dev.off() doesn't work. I tried this with different versions of R, and the problem persists.
You should use ggsave instead of the jpeg(); print(p); dev.off() sequence. ggsave is a wrapper that does exactly what you intend to do with your function, except that it offers more options and versatility. You can specify the type of output explicitly, e.g. jpg or pdf, or it will guess from your filename extension.
So your code might become something like:
p <- qplot(1:20, 1:20)
ggsave(filename="a.jpg", plot=p)
See ?ggsave for more details
The reason why the original behaviour in your code doesn't worked is indeed a frequently asked question (on stackoverlflow as well as the R FAQs on CRAN). You need to insert a print statement to print the plot. In the interactive console, the print is silently execututed in the background.
These plots have to be printed:
ff <- function(){
jpeg("a.jpg")
p <- qplot(1:20, 1:20)
print(p)
dev.off()
}
ff()
This is a very common mistake.

Resources