Creating Multiple Plots in Multiple files with ggplot2 in R - 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()
}

Related

Why am I unable to see multiple plots appear with a for loop?

This is my code which is part of a larger script.
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
png(paste(survPath,"/surv_",d1,".png",sep=""))
plot(survfit1,xlab="Years",ylab="Survival probability",xmax=xmax1)
}
I don't have a good idea of what this code does yet, so I'm trying to look at each individual plot to see what it is. The problem is, whenever I run this in the R command line in the terminal in linux, nothing appears. I have to use dev.off() multiple times and then rerun this code:
plot(survfit1)
for something to appear. How can I see all the plots?
Sounds like this is really what you want:
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
x11() ## open up new graphical window for each plot (to avoid overwriting)
plot(survfit1,xlab="Years",ylab="Survival probability",
xmax=xmax1, main = d1) ## use different titles to distinguish those plots
}
This will produce plots on normal graphical windows.
If you want to use the original code, you'd better do this way:
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
png(paste(survPath,"/surv_",d1,".png",sep=""))
plot(survfit1,xlab="Years",ylab="Survival probability",xmax=xmax1)
dev.off()
}
Then, have a look at the directory given by getwd(). All the plots are saved in png files.
Calling Sys.sleep(.1) might help during the for loop. Maybe try:
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
Sys.sleep(.1)
png(paste(survPath,"/surv_",d1,".png",sep="", collapse="))
plot(survfit1,xlab="Years",ylab="Survival probability",xmax=xmax1)
dev.off()
}

Writing printer friendly pdfs with ggplot2 and many (>25000) dots or lines

I am creating a lot of facet plots with ggplot2 and writing those into a multiple page pdf file. I added some sample data as an example.
reps <- 1000
df <- data.frame(id=rep(letters[1:25], each=reps),
group=rep(LETTERS[1:25], each=reps),
x=runif(reps*25),
y=runif(reps*25))
pdf('test.pdf', width=11.69, height=8.27)
for(i in seq(4)) {
p <- ggplot(df, aes(x,y, group=group)) +
geom_line() + geom_point() +
facet_wrap(~ id)
print(p)
}
dev.off()
To view the PDF it is really nice, but most of the time these big files with vector graphics kill my print jobs.
Is there a way to handle this properly? For example, creating PNG images and saving them in multipage PDFs? Or, am I the only one having problems printing such files?
I am aware that the PNG file might be bigger, but I guess the printer can handle it much better than a vector graphic.
The only solution I found so far is the following: https://helpx.adobe.com/acrobat/kb/quick-fix-print-pdf-image.html
I think this might be the best way since the creation of PDF is the same, you just switch to "print as image" in the advance printing dialog in Acrobat Reader...

output ggplot results in one pdf but several pages in R

I have at least 10 plots by ggplot(we can call them plot1, plot2 ....). I can output them into separate pdf files. But I prefer to output them in only one pdf file but several pages. One page, one plot from ggplot.
I tried to list all plots and use ggsave but it can not work. Any idea or script can help? Thank you
See the pdf function for this.
For three plots it would look like this (saving into your working directory with default naming). Run through dev.off line before you can open file.
pdf()
plot1
plot2
plot3
dev.off()
If your plots are already stored in a list named list1:
pdf()
list1
dev.off()
Based on aosmith's answer, here's a simple wrapper function to save lists of ggplot2 plots to a single pdf.
GG_save_pdf = function(list, filename) {
#start pdf
pdf(filename)
#loop
for (p in list) {
print(p)
}
#end pdf
dev.off()
invisible(NULL)
}

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

Getting foreach() and ggplot2 to get along

I have a set of survey data, and I'd like to generate plots of a particular variable, grouped by the respondent's country. The code I have written to generate the plots so far is:
countries <- isplit(drones, drones$v3)
foreach(country = countries) %dopar% {
png(file = paste(output.exp, "/Histogram of Job Satisfaction in ", country$key[[1]], ".png", sep = ""))
country.df <- data.frame(country) #ggplot2 doesn't appreciate the lists nextElem() produces
ggplot(country.df, aes(x = value.v51)) + geom_histogram()
dev.off()
}
The truly bizarre thing? I can run the isplit(), set country <- nextElem(countries), and then run through the code without sending the foreach line - and get a lovely plot. If I send the foreach, I get some blank .png files.
I can definitely do this with standard R loops, but I'd really like to get a better grasp on foreach.
You need to print the plot if you want it to display:
print(ggplot(country.df, aes(x = value.v51)) + geom_histogram())
By default, ggplot commands return a plot object but the command itself does not actually display the plot; that is done with the print command. Note that when you run code interactively, results of commands get printed which is why you often don't need the explicit print. But when wrapping in a foreach, you need to explicitly print since the results of the commands in the body will not be echoed.

Resources