ggplot2 plot fill page in landscape (pdf) - r

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)

Related

Problem in making multiple PDF pages with gridExtra in R

I used grid.table from the package gridExtra in R to make a PDF report of my Stat tests outputs.
I use this code:
library(gridExtra)
my_text = readLines("Dunnett.txt")
my_text2 = readLines("Shapiro-Wilk.txt")
pdf(sprintf("Results.pdf"), width=11, height=8)
grid.table(my_text)
grid.table(my_text2)
dev.off()
#cleanup
file.remove("Dunnett.txt")
file.remove("Shapiro-Wilk.txt")
But the problem is that my grid.table1 and 2 overlay on each other in one page. I want them be saved in 2 different pages.
Does anybody know how to do that?
library(grid)
grid::grid.newpage()

How to increase resolution of ggplots when exporting using officer R

I want to export charts to a PPT and am using the officer package to achieve the same. However, the default resolution of the charts is low and I would like to change that. I am currently using the following call
ph_with_gg(p1,type = "chart",res = 1200)
where p1 is a ggplot object. On running this, I get the following error:
Error in png(filename = file, width = width, height = height, units =
"in", :
formal argument "res" matched by multiple actual arguments
Would really appreciate the help around this
Rather than using png, for high-resolution plots in PPT you should be using vector graphics.
See under extensions:
Vector graphics with package rvg
The package rvg brings an API to
produce nice vector graphics that can be embedded in PowerPoint
documents or Excel workbooks with officer.
This package provides functions dml() and ph_with() corresponding method to export ggplots to .pptx as vector graphics.
Example:
library(ggplot2)
library(officer)
library(rvg)
library(magrittr)
data(iris)
read_pptx() %>%
add_slide(layout='Title and Content',master='Office Theme') %>%
ph_with('Iris Sepal Dimensions', location = ph_location_type(type="title")) %>%
ph_with(dml( ggobj=
ggplot(iris, aes(x=Sepal.Length,y=Sepal.Width,col=Species)) +
geom_point()), location = ph_location_type(type="body")) %>%
print('iris_presentation.pptx')
As an additional benefit, you will be able to edit the charts in PowerPoint. For example, if you decided to capitalize the names of the 3 species, you could just edit the chart instead of editing the data and regenerating the slides. (You can also make the plots non-editable, but editable is the default.)
Is it important that the plot is saved to a presentation in the code?
Otherwise using:
ggsave(filename = file, p1, width = width, height = height, dpi = dpi)
will give you a png of any resolution you need..
(provided that filename ends with .png and you set width, height and dpi to appropriate values)

Edit style of grid.arrange title. Bold, italic etc. R

I am creating a multi plot in R using grid.arrange, and wanted to change my title so that it is bold (and italic if possible).
As this is a general question, I will not include the code for my plots, but the code I am using to make my multi plot is:
grid.arrange(g1, g3, g4+theme(legend.position="none"),mylegend, top="Test title",
layout_matrix=matrix(c(1,1,2,3,4,4), ncol=2, byrow=TRUE),heights=c(1,1.5,0.3))
Are there any additional arguments which can be passed to the top argument to change the font face?
I've worked it out myself..
You can use the text_grob function to create a text element, which can then be passed to the top function of grid.arrange.
For example,
##title1=textGrob("Test title", gp=gpar(fontface="bold")) ## this does not work anymore
title1=text_grob(main, size = 15, face = "bold") #### this worked for me
grid.arrange(g1, g3, g4+theme(legend.position="none"),mylegend, top=title1, ncol=2, byrow=TRUE),heights=c(1,1.5,0.3))
Just a small update:
Instead of using text
textGrob
use text_grob from ggpubr package

How to export arrangeGrob output via win.metafile()

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()

Plot as bitmap in PDF

I am currently working on CGH array results, which involve several plots of dozens of thousands of points, and i would like to benefit from the multiple page feature of the PDF device and the lightness of the PNG image format.
The problem is that the PDF device stores the plots as vectorial drawings, so the PDF files are huge and take several minutes to open. I wonder if R can plot as multiple bitmaps embedded in a single PDF file, as i know the PDF format able to handle it.
Here is a simple example, the PDF file is about 2 Mo while the png ones are about 10 Ko, so I'd like a PDF file of about 20 Ko.
png("test%i.png")
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
dev.off()
pdf("test.pdf", onefile=TRUE)
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
dev.off()
Use the png driver to create a PNG file of an acceptable resolution. Make your plot to that. Close the png device.
Then use readPNG from package:png to read it in.
Next open a PDF driver, create a blank plot with no margins and bounds at (0,0) (1,1) and draw the png to that using rasterImage. Add extra pages by creating fresh plots. Close PDF driver.
That should give you a PDF with bitmapped versions of the plots. There's a few tricky bits in getting the plots set up right, and the png resolution is crucial, but I think the above has all the ingredients.
> png("plot.png")
> makeplot(100000) # simple function that plots 100k points
> dev.off()
X11cairo
2
> plotPNG = readPNG("plot.png")
> pdf("plot.pdf")
> par(mai=c(0,0,0,0))
> plot(c(0,1),c(0,1),type="n")
> rasterImage(plotPNG,0,0,1,1)
> dev.off()
Then check plot.pdf...
Here's a solution that gets you close (50kb) to your desired file size (25kb), without requiring you to install LaTeX and/or learn Sweave. (Not that either of those are undesirable in the long-run!)
It uses the grid functions grid.cap() and grid.raster(). More details and ideas are in a recent R-Journal article by Paul Murrell (warning : PDF):
require(grid)
# Make the plots
dev.new() # Reducing width and height of this device will produce smaller raster files
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
cap1 <- grid.cap()
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6, col="red")
cap2 <- grid.cap()
dev.off()
# Write them to a pdf
pdf("test.pdf", onefile=TRUE)
grid.raster(cap1)
plot.new()
grid.raster(cap2)
dev.off()
The resulting pdf images appear to retain more detail than your files test1.png and test2.png, so you could get even closer to your goal by trimming down their resolution.
To include multiple plots in your pdf, set onefile = TRUE.
pdf("test.pdf", onefile = TRUE)
plot(1:5)
plot(6:10)
dev.off()
To make those plots PNGs rather than native PDF plots will require a tiny bit more effort. Create all your plots as PNGs, like so:
png("test%01d.png")
plot(1:5)
plot(6:10)
dev.off()
Then create a LaTeX document that includes those PNGs. You can do that from R by using Sweave (but how to do that is big enough to be its own question). There's a decent introductory example here.
How abouta Sweave solution?
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\SweaveOpts{pdf = FALSE, eps = FALSE}
\DeclareGraphicsExtensions{.png}
\begin{document}
\title{Highly imaginative title}
\author{romunov}
\maketitle
<<fig = TRUE, png = TRUE, echo = FALSE>>=
plot(1:10, 1:10)
#
\end{document}

Resources