I have a working loop which generates and can save individual plots from each file saved in a directory.
I want to plot all of the returned plots in a single file as a 2x2 grid over multiple pages but cannot do this.
I have tried to save the plot objects in a list
pltList <- list()
pltList[]
for (f in 1:length(files)){
plot_object <- ggplot2(...) #make ggplot2 plot
print(plot_object)
pltList[[f]] <- plot_object #save ggplot2 plot in list
}
jpeg(filename.jpg)
par(mfrow=c(2,2)) #to generate 2x2 plot per page
print(pltList[[1]])
print(pltList[[2]])
...
print(pltList[[f]])
dev.off()
The problem is that the resulting saved .jpg file only contains the last plot and not a 2x2 grid of all plots over many pages which is what I want.
EDIT
My first problem is how to save each plot from the loop in the list - how can I view the saved objects from the list to make sure they have been saved correctly?
When I do print(pltList[1]), the resulting output is:
function (x, y, ...)
UseMethod("plot")
<bytecode: 0x0000000010f43b78>
<environment: namespace:graphics>
rather than the actual plot. It seems that the plots are not being saved in the list as expected. How can I correct for this?
Hopefully, once this is fixed, your plotting suggestions will work.
I did recently the same. I used grid.arrange().
library(ggplot2)
library(gridExtra)
library(grid)
p1<-ggplot()+geom_line(aes(x=1:10,y=1:10))
p2<-ggplot()+geom_line(aes(x=1:10,y=1:10))
p3<-ggplot()+geom_line(aes(x=1:10,y=1:10))
p4<-ggplot()+geom_line(aes(x=1:10,y=1:10))
grid.arrange(p1,p2,p3,p4, ncol=1, top=textGrob("Multiple Plots", gp=gpar(fontsize=12, font = 2)))
Assuming you need a PDF output where every page has multiple plots plotted as one, e.g.: if there are 12 plots then 4 plots per page.
Try this example:
library(ggplot2)
library(cowplot)
# list of 12 dummy plots, only title is changing.
pltList <- lapply(1:12, function(i){
ggplot(mtcars,aes(mpg,cyl)) +
geom_point() +
ggtitle(paste("Title",i))})
# outputs 3 jpeg files with 4 plots each.
for(i in seq(1,12,4))
ggsave(paste0("Temp",i,".jpeg"),
plot_grid(pltList[[i]],
pltList[[i+1]],
pltList[[i+2]],
pltList[[i+3]],nrow = 2))
# or we can output into 1 PDF with 3 pages using print
pdf("TempPDF.pdf")
for(i in seq(1,12,4))
print(plot_grid(pltList[[i]],
pltList[[i+1]],
pltList[[i+2]],
pltList[[i+3]],nrow = 2))
dev.off()
EDIT:
Another way using gridExtra, as suggested by #user20650:
library(gridExtra)
#output as PDF
pdf("multipage.pdf")
#use gridExtra to put plots together
marrangeGrob(pltList, nrow=2, ncol=2)
dev.off()
Related
I am trying to create a multipage pdf with multiple plots per page from a list of plots created using base R plot() function. I know this is easy if the plots are created using ggplot2, but the plots I have come from a package that uses base R plot(). I store the plots in a list and then want to create a pdf from the list of plots. The following section of code gives a working example of what I am after:
# This creates 1 file with multiple pages & each page having 4 plots
pdf(file = if(TRUE) "Rplot.pdf" else "Rplot%03d.pdf",
paper = "letter")
par(mfrow=c(nrow = 2, ncol = 2))
for (i in 1:6){
x=rnorm(5)
y=rnorm(5)
plot(x,y)
title(paste0("Plot ",i))
}
I am trying to obtain the same result when the plots are stored in a list, as in the following:
# Create plots and store in a list
listofplots <- list()
for (i in 1:6){
x=rnorm(5)
y=rnorm(5)
plot(x,y)
title(paste0("Plot ",i))
listofplots[[i]] <- recordPlot()
}
# Create pdf
pdf(file = "Rplot.pdf")
par(mfrow=c(nrow = 2, ncol = 2))
for(i in 1:6) {
print(listofplots[[i]])
}
dev.off()
The above code generates 1 file, with 1 plot per page, rather than multiple plots per page. Clearly I am missing something simple.
I have created one function that contains two types of plots and it will give you one image. However, the title of this image will change depending on one list, so, you will have several plots but different title.
(The original function will change the numbers that the plot uses but, in essence, is what I need).
This is the example that I have created.
list_genes <- c("GEN1", "GEN2", "GEN3")
myfunction <- function(x,y){
for(gene in list_genes){
# This to draw both plots
par(mfrow=c(2,1))
plot(x,y, main=paste0("Plot of ", gene))
hist(x, main=paste0("Plot of ", gene))
}
}
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
Since the list has 3 elements, we get 3 plots.
However, as I need to create a presentation with all the plots that I generate, I found this post with a solution to create slides for several plots inside a for loop. It is what I want, but for that, I need to save my plots into a list/variable.
object <- myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
> object
NULL
I found this post (which gives you an interesting solution) but, the plots still cannot be saved into an object.
calling_myfunc <- function(){
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
}
calling_myfunc()
object <- calling_myfunc()
> object
NULL
My final objective is to create a presentation (automatically) with all of the plots that I generate from my function. As I saw in this post. But I need to save the plots into a variable.
Could anyone help me with this?
Thanks very much in advance
Although I couldn't find the way to save the plots into an object, I found a way to create a presentation with those images thanks to this post and the export package.
library(export)
list_genes <- c("GEN1", "GEN2", "GEN3")
myfunction <- function(x,y){
for(gene in list_genes){
# This to draw both plots
par(mfrow=c(2,1))
plot(x,y, main=paste0("Plot of ", gene))
hist(x, main=paste0("Plot of ", gene))
graph2ppt(file="plots.pptx", width=6, height=5,append=TRUE) } }
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
Of course, the width and height of the plots can be changed or put them as a parameter in the function.
Since the package is not available in CRAN for my current R version (4.1.2), I downloaded it from GitHub:
devtools::install_github("tomwenseleers/export")
In addition, I have found another package that I can use for the same purpose (although it adds one extra slide at the beginning, I don't know why)
library(eoffice)
list_genes <- c("GEN1", "GEN2", "GEN3")
myfunction <- function(x,y){
for(gene in list_genes){
# This to draw both plots
par(mfrow=c(2,1))
plot(x,y, main=paste0("Plot of ", gene))
hist(x, main=paste0("Plot of ", gene))
topptx(file="plots.pptx", width=6, height=5,append=TRUE)
}
}
myfunction(x=c(1,5,6,2,4),y=c(6,10,53,1,5))
PS: I found the solution to create a presentation --> How to create a presentation in R with several plots obtained by a function?
I am using ggplot and ggplot.multiplot function to plot multiplots (2 columns plots) per page but I couldnt make it. please help
I have a list of ggplots in variable plot_list and using function ggplot2.multiplot to plot 2 plot per page. But it plot all figures in one page that messed up. I want two plot per page in single figure.
>plot_list ## ggplot saved in a list though i have long list to plot
[[1]]
[[2]]
[[3]]
[[4]]
In both case i tried but all four plots plotted in same page:
library(easyGgplot2)
library(ggplot2)
ggplot2.multiplot(plotlist = plot_list, cols=2)
ggplot2.multiplot(plotlist = plot_list)
However its work as:
ggplot2.multiplot(plot_list[[1]],plot_list[[2]],cols=2)
ggplot2.multiplot(plot_list[[3]],plot_list[[4]],cols=2)
But i have long list of figures to generate in a single pdf !!
I also i have tried library("cowplot") but got error while using list of figures.
plot_grid(plot_list, ncol = 2, nrow = 1)
Error in ggplot_to_gtable(x) :
Argument needs to be of class "ggplot" or "gtable"
Please help.
Thanks
there's gridExtra::marrangeGrob
library(ggplot2)
library(gridExtra)
pl <- replicate(5, ggplot(), simplify=FALSE)
ml <- marrangeGrob(pl, nrow=1, ncol=2)
ggsave("multipage.pdf", ml)
for your cowplot problem, there is an argument plotlist in the plot_grid function (https://rdrr.io/cran/cowplot/man/plot_grid.html):
plot_grid(plotlist=plot_list)
should work
I'm attempting to step through a dataset and create a histogram and summary table for each factor and save the output as a .svg . The histogram is created using ggplot2 and the summary table using summary().
I have successfully used the code below to save the output to a single .pdf with each page containing the relevant histogram/table. However, when I attempt to save each histogram/table combo into a set of .svg images using ggsave only the ggplot histogram is showing up in the .svg. The table is just white space.
I've tried using dev.copy Cairo and svg but all end up with the same result: Histogram renders, but table does not. If I save the image as a .png the table shows up.
I'm using the iris data as a reproducible dataset. I'm not using R-Studio which I saw was causing some "empty plot" grief for others.
#packages used
library(ggplot2)
library(gridExtra)
library(gtable)
library(Cairo)
#Create iris histogram plot
iris.hp<-ggplot(data=iris, aes(x=Sepal.Length)) +
geom_histogram(binwidth =.25,origin=-0.125,
right = TRUE,col="white", fill="steelblue4",alpha=1) +
labs(title = "Iris Sepal Length")+
labs(x="Sepal Length", y="Count")
iris.list<-by(data = iris, INDICES = iris$Species, simplify = TRUE,FUN = function(x)
{iris.hp %+% x + ggtitle(unique(x$Species))})
#Generate list of data to create summary statistics table
sum.str<-aggregate(Sepal.Length~Species,iris,summary)
spec<-sum.str[,1]
spec.stats<-sum.str[,2]
sum.data<-data.frame(spec,spec.stats)
sum.table<-tableGrob(sum.data)
colnames(sum.data) <-c("species","sep.len.min","sep.len.1stQ","sep.len.med",
"sep.len.mean","sep. len.3rdQ","sep.len.max")
table.list<-by(data = sum.data, INDICES = sum.data$"species", simplify = TRUE,
FUN = function(x) {tableGrob(x)})
#Combined histogram and summary table across multiple plots
multi.plots<-marrangeGrob(grobs=(c(rbind(iris.list,table.list))),
nrow=2, ncol=1, top = quote(paste(iris$labels$Species,'\nPage', g, 'of',pages)))
#bypass the class check per #baptiste
ggsave <- ggplot2::ggsave; body(ggsave) <- body(ggplot2::ggsave)[-2]
#
for(i in 1:3){
multi.plots<-marrangeGrob(grobs=(c(rbind(iris.list[i],table.list[i]))),
nrow=2, ncol=1,heights=c(1.65,.35),
top = quote(paste(iris$labels$Species,'\nPage', g, 'of',pages)))
prefix<-unique(iris$Species)
prefix<-prefix[i]
filename<-paste(prefix,".svg",sep="")
ggsave(filename,multi.plots)
#dev.off()
}
Edit removed theme tt3 that #rawr referenced. It was accidentally left in example code. It was not causing the problem, just in case anyone was curious.
Edit: Removing previous answer regarding it working under 32bit install and not x64 install because that was not the problem. Still unsure what was causing the issue, but it is working now. Leaving the info about grid.export as it may be a useful alternative for someone else.
Below is the loop for saving the .svg's using grid.export(), although I was having some text formatting issues with this (different dataset).
for(i in 1:3){
multi.plots<-marrangeGrob(grobs=(c(rbind(iris.list[i],table.list[i]))),
nrow=2, ncol=1,heights=c(1.65,.35), top =quote(paste(iris$labels$Species,'\nPage', g,
'of',pages)))
prefix<-unique(iris$Species)
prefix<-prefix[i]
filename<-paste(prefix,".svg",sep="")
grid.draw(multi.plots)
grid.export(filename)
grid.newpage()
}
EDIT: As for using arrangeGrob per #baptiste's comment. Below is the updated code. I was incorrectly using the single brackets [] for the returned by list, so I switched to the correct double brackets [[]] and used grid.draw to on the ggsave call.
for(i in 1:3){
prefix<-unique(iris$Species)
prefix<-prefix[i]
multi.plots<-grid.arrange(arrangeGrob(iris.list[[i]],table.list[[i]],
nrow=2,ncol=1,top = quote(paste(iris$labels$Species))))
filename<-paste(prefix,".svg",sep="")
ggsave(filename,grid.draw(multi.plots))
}
There is very convenient way of plotting multiple graphs and that's with gridExtra - grid.arrange:
grid.arrange(plot1,plot2,plot3,plot4,plot5,plot6,plot7,plot8,plot9, ncol=3)
The above command draws 3x3 graphs in one window.
Now, I'm using my own lattice setup to draw unique lines etc. via
trellis.par.set(my.setup)
However using the grid.arrange command for plotting multiple plots won't pass on the setup as the output plots are in default colours.
So the question is how to pass on the my.setup onto grid.arrange or alternatively how to plot easily multiple graphs in one go for lattice.
EDIT: Reproducible example:
Data <- data.frame(Col1=rnorm(10,0,1),Col2=rexp(10,2),Col3=rnorm(10,2,2),Col4=runif(10,0,2),
Time=seq(1,10,1))
trellis.par.set(col.whitebg())
newSet <- col.whitebg()
newSet$superpose.symbol$col <- c("blue3","orange2","gray1","tomato3")
newSet$superpose.symbol$pch <- 1
newSet$superpose.symbol$cex <- 1
newSet$superpose.line$col <- c("blue3","orange2","gray1","tomato3")
trellis.par.set(newSet)
Plot1 <- xyplot(Col1+Col2~Time, Data, type="spline")
Plot2 <- xyplot(Col2+Col3~Time, Data, type="spline")
Plot3 <- xyplot(Col1+Col3~Time, Data, type="spline")
Plot4 <- xyplot(Col3+Col4~Time, Data, type="spline")
grid.arrange(Plot1,Plot2,Plot3,Plot4, ncol=2)
I guess it's got something to do with the plot.trellis method not finding the global theme settings when it's wrapped in gridExtra::drawDetails.lattice. I don't understand these lattice options, but as far as I recall you can specify them explicitly at the plot level too,
pl = list(Plot1, Plot2, Plot3, Plot4)
# do.call(grid.arrange, c(pl, nrow=1))
do.call(grid.arrange, c(lapply(pl, update, par.settings=newSet), list(nrow=1)))