Save plots generated within a loop in R - r

I am looking for a way to save ggplots and flextables to the workspace and later combine these objects that were generated within a loop.
Here is a simple example:
for (i in 1:3) {x<-rnorm(20, 5, 5-i); hist(x)}
In this example, x is overwritten every time and a new histogram is generated. I would want to store each histogram that is generated within the loop in the current workspace and later combine those histograms in one plot (without having to actually save each one of them). How can I go about that best?
Thanks a lot in advance!

We could set the par and get the plots into a single page
par(mfrow = c(3, 1))
for (i in 1:3) {
x<-rnorm(20, 5, 5-i)
hist(x)
}
If we want to store the plots and print, then create a NULL list to store the objects, and then do the plotting later
p1 <- vector('list', 3)
for(i in seq_along(p1)) {
x<- rnorm(20, 5, 5-i)
p1[[i]] <- hist(x)
}
par(mfrow = c(3, 1))
for(p in p1) plot(p)

Related

Saving S3 aggr object in a way mice_plots can be visualized by ggplot in a grid arrangement

I am using a for loop to loop through a dataset and produce a mice_plot per category. In the for loop, I would like to save the produced mice_plot so that I can later plot them all in a grid.
my code looks like this atm:
for center in unique(df$center){
dispatch_centers <- list()
mice_plot <- aggr(center, ...)
# save mice_plot some how in a way I can later open it with ggplot
as.grob()?
#add to list
center_plots[[center]] <- mice_plot
}
grid.arrange(grobs = center_plots, ncol = 2)
However, I do not understand the aggr() object nor how to save it so I can later handle it with ggplot2. Does anyone have any ideas?

From a list of base R plots, create a multipage pdf with multiple plots per page

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.

How to save multiple ggplot charts in loop for using grid.arrange

I have a for loop that creates a different ggplot for a different set of parameters each time through the loop. Right now I am printing N different charts one at a time. I would like to save them so I can use grid.arrange to put them all on one page. This doesn't work:
p <- vector(length = N)
for(i in 1:N)
p[i] <- ggplot( ........
...
...
grid.arrange(p[1], p[2], .. p[N], nrow = 4)
Is there a way to save the plots for later plotting a grid of plots on a page outside the loop, or is there a way to set up the grid specification before the loop and and produce the gridded plot on the fly as the loop is executed (e.g., the way par is used with plot)?
You rarely want to use for loops in R. In R's lapply(). In a single step:
do.call(
grid.arrange,
lapply(data, function(f){
ggplot(f, ...)
}
)
EDIT:
If you want to store the list for later plotting:
plot_objects <- lapply(data, function(f) {
ggplot(f, ...)
})
do.call(grid.arrange, plot_objects)
This could be solved by initiating a list to store the plot objects instead of vector
p <- vector('list', N)
for(i in seq_len(N)) {
p[[i]] <- ggplot(...)
}
grid.arrange(p[[1]], p[[2]], ..., p[[N]], nrow = 4)

Prevent a plot to be overwrite in a for loop

I am trying to create three different plots in a for loop and then plotting them together in the same graph.
I know that some questions regarding this topic have already been asked. But I do not know what I am doing wrong. Why is my plot being overwritten.
Nevertheless, I tried both solutions (creating a list or using assign function) and I do not know why I get my plot overwriten at the end of the loop.
So, the first solution is to create a list:
library(gridExtra)
library(ggplot2)
out<-list()
for (i in c(1,2,4)){
print(i)
name= paste("WT.1",colnames(WT.1#meta.data[i]), sep=" ")
print(name)
out[[length(out) + 1]] <- qplot(NEW.1#meta.data[i],
geom="density",
main= name)
print(out[[i]])
}
grid.arrange(out[[1]], out[[2]], out[[3]], nrow = 2)
When I print the plot inside the loop, I get what I want...but of course they are not together.
First Plot
When I plot them all together at the end, I get the same plot for all of the three: the last Plot I did.
All together
This is the second option: assign function. I have exactly the same problem.
for ( i in c(1,2,4)) {
assign(paste("WT.1",colnames(WT.1#meta.data[i]),sep="."),
qplot(NEW.1#meta.data[i],geom="density",
main=paste0("WT.1",colnames(WT.1#meta.data[i]))))
}
You're missing to dev.off inside the loop for every iteration. Reproducible code below:
library(gridExtra)
library(ggplot2)
out<-list()
for (i in c(1,2,3)){
print(i)
out[[i]] <- qplot(1:100, rnorm(100), colour = runif(100))
print(out[[i]])
dev.off()
}
grid.arrange(out[[1]], out[[2]], out[[3]], nrow = 2)

Using loops to set layout dimensions R

I am not sure this is possible. Basically what I'm trying to do is create a plot loop where if more than 5 plots are to be plotted then a second row of plots should be done ncol = to 5- number of plots.
data=matrix(rbinom(10*1000, 1, .5), ncol=10)
subdata1 = data[1:5,]
subdata2 = data[1:7,]
if (nrow(subdata1) <= 5){
par(mfrow = c(1, nrow(subdata1)))
for (i in 1:nrow(subdata1)){
plot(as.numeric(subdata1[i,1:5]), as.numeric(subdata1[i,6:10]))
}
}else{
## need to figure out how to bind layout based on nrows
## i.e. subdata2
return(NULL)
}
Basically I'm building a shinny app where based on users selections there could be anywhere from 1 plot to 10 and I want to be able to display this as nice as possible.
If you want to be as nice as possible perhaps you should look at the easy option of using the n2mfrow() function. This takes a number and turns it into the best row/column combination. With your example you can do par(mfrow = n2mfrow(nrow(data))) before running your for-loop plot. However, this will not fix the plots to 5 columns.

Resources