Multiple plotting device in R - r

To save multiple plots in a pdf, I do this:
pdf("plot1.pdf")
for(i in 1:10){
p <- plot(rnorm(10))
p
}
dev.off()
Is there any way I can open two pdf and print different plots in them. Something like
pdf("plot1.pdf")
pdf("plot2.pdf")
for(i in 1:10){
p1 <- plot(rnorm(10))
p1 # print this in plot1.pdf
p2 <- plot(rnorm(100))
p2 # print this in plot2.pdf
}
dev.off()

You can only have one graphics device active at a time, but you can switch between them. R tracks a list of open devices (dev.list()) in the order in which you create them. For example you can do
pdf("plot1.pdf")
pdf("plot2.pdf")
for(i in 1:3){
dev.set(dev.prev()) #go back to plot1.pdf
plot(rnorm(10))
dev.set(dev.next()) # jump ahead to plot2.pdf
plot(rnorm(100))
}
dev.off()
dev.off()
(Note it doesn't make sense to store the result of plot(rnorm(10)) to a variable because it doesn't return anything. Base plotting typically just have the side effect of drawing to the screen.)

Related

How do I use qqplot() and assign the output to an object?

I'd like to make an object that has a QQ chart
This is my code
qqnorm(titanic$age)
qqline(titanic$age)
In ggplot, I can layer geoms on top of each other, so they can be in one object
What's the equivalent for this case?
Here's some code as an example. I had to use a different dataset, as the "Titanic" dataset's age column is non-numeric:
data("AirPassengers")
qqnorm(AirPassengers)
qqline(AirPassengers)
lines(x = 1:length(AirPassengers), rep(300, 144))
p <- recordPlot()
p
edit: to disable the plot:
dev.control('inhibit')
plot(rnorm(10))
p <- recordPlot()
dev.off()
in a loop:
for(i in 1:10){
# dev.control('inhibit')
plot(rnorm(10))
p <- recordPlot()
# dev.off()
l_plots[[i]] <- p
}
Somehow it seems difficult to combine the approaches. How about you just delete the plots in the plotting window after creating them?

How to print all recorded plots in a list in R Markdown

this is my first question at StackOverflow. If I am doing something wrong let me know to improve the next questions.
I am starting with R Markdown and I have some troubles to print recorded plots with a for loop. Well, before I run Rmarkdown file, I run R function that generate a list of several data frames and plots.
To make it easier I put here a simplified reproducible example of this list just with plot objects.
x <- c(1,2,3,4,5)
y <- c(1,2,3,4,5)
plot(x,y)
abline(h=1)
p1.1 <- recordPlot()
plot(x,y)
abline(h=3)
p1.2 <- recordPlot()
plot(x,y)
abline(h=4)
p2.1 <- recordPlot()
plot(x,y)
abline(h=6)
p2.2 <- recordPlot()
lista<-NULL
lista["p1.1"] <- list(p1.1)
lista["p1.2"] <- list(p1.2)
lista["p2.1"] <- list(p2.1)
lista["p2.2"] <- list(p2.2)
save(new_list, file = "Data.RData")
Then I load this list in R Markdown file like this:
```{r setup}
knitr::opts_chunk$set(echo = TRUE,fig.keep = "all")
load("Data.RData")```
And I try to print this plots like this:
```{r,echo=FALSE, results='asis',fig.keep='all'}
for (i in c(1,2)){
for(j in c(1,2)){
print(lista[[paste(paste("p",i,sep=""),j,sep=".")]])
}
}```
When I run Knitr to obtain HTML file the result is that just the last plot of the for loop is shown.
I have tried use lapply instead of for loop, but it did not work for me. Also I tried to use replayPlot function print(replayPlot(lista[[paste(paste(paste("p",i,sep=""),".",sep=""),j,sep="")]])) with the same result.
Is there any way to solve this without modifying the previous R function that generate the plot list?
Thank you for the answers.
The syntax you use would probably be OK with a list of ggplot objects, but with base plot objects, you need to call plot.new() so that the next plot in the list doesn't overwrite the previous one:
---
title: "test"
output: html_document
---
## Define plots
```{r}
x <- c(1,2,3,4,5)
y <- c(1,2,3,4,5)
plot.new()
plot(x,y)
abline(h=1)
p1.1 <- recordPlot()
plot.new()
plot(x,y)
abline(h=3)
p1.2 <- recordPlot()
plot.new()
plot(x,y)
abline(h=4)
p2.1 <- recordPlot()
plot.new()
plot(x,y)
abline(h=6)
p2.2 <- recordPlot()
lista<-NULL
lista["p1.1"] <- list(p1.1)
lista["p1.2"] <- list(p1.2)
lista["p2.1"] <- list(p2.1)
lista["p2.2"] <- list(p2.2)
```
# Print list
```{r,echo=F}
for (i in c(1,2)){
for(j in c(1,2)){
# Needed to avoid overwrite
plot.new()
print(lista[[paste(paste("p",i,sep=""),j,sep=".")]])
}
}
```
Note that you can simplify the syntax of the loops:
for(p in lista) {
plot.new()
print(p)
}
You don't need a loop to plot each ggplot saved in a list. Much simpler:
```{r,echo=FALSE}
print(lista)
```
This automatically plots every element of the list (each plot) to the Markdown.

Saving ggplot graphs to pdf not formatting correctly in PDF

This is a follow on question to my original here
I am currently trying to save the outputs of a ggplot graph to .pdf but I am running into some problems.
I run the following on the dput data on the original question (I repaste everything below).
library(gridExtra)
pdf("Plots.pdf", onefile = TRUE)
for(j in 1:length(plotList)) {
grid.arrange(plotList[[j]], nrow = 2)
}
dev.off()
This saves the files as a pdf document but instead of getting two graphs per page I get one graph which takes up half a page. Is it possible to resize the graphs, when I select nrow = 3 I get the same problem, I get one graph in the top 3rd / half of the page and a blank space for the rest. I provide a screen shot of the output:
Here is a minimal example:
# Make empty list for plots
plotList <- list()
# Build plots
library(ggplot2)
for(i in 1:2){
plotList[[i]] <-
ggplot(mtcars, aes(mpg, cyl)) +
geom_point() +
labs(title = i)
}
# Save plots
library(gridExtra)
pdf("Plots.pdf", onefile = TRUE)
for(j in 1:length(plotList)) {
grid.arrange(plotList[[j]], nrow = 2)
}
dev.off()
Credit to #LachlanO
You problem comes from how you are calling grid.arrange. By including it in a loop, you are telling it to create multiple separate plots, like this:
grid.arrange(plotList[[1]], nrow = 2)
grid.arrange(plotList[[2]], nrow = 2)
grid.arrange(plotList[[3]], nrow = 2)
What you actually are trying to do is create one grid.arrange object which contains all the plots. To do this, you need call the function against the list:
do.call("grid.arrange", c(plotList, nrow=2))
Alternatively, you can use the cowplot package and use:
cowplot::plot_grid(plotlist = plotList, nrow = 2)
So to save the PDF you can use:
pdf("Plots.pdf", onefile = TRUE)
do.call("grid.arrange", c(plotList, nrow=2))
dev.off()

Plot multiple ggplot2 on same page

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

plot multiple figures interactively with split.screen and hold one constant

I am using R to plot a multifgure image with interactive capability in one of them. I'm using split.screen to do this (as I tried unsuccesfuly to do it right with par() and base R graphics.
My goal is to hold the display of each screen(1) jth plot, while the screen(2) plot figure updates interactively k times..
But even though I set erase = FALSE or TRUE, each time it iterates through the subloop, the first plot is cleared and displays a blank image. Any ideas on how to hold the first plot image, each time the sub loop, k updates its graphics?
split.screen(figs=c(1,2),erase=TRUE)
for(j in 1:5){
screen(1)
plot(rnorm(3))
screen(2)
for(k in 1:5){
plot(rnorm(3))
par(ask=TRUE)
}
}
update from help.
These functions are totally incompatible with the other mechanisms for arranging plots on a device: par(mfrow), par(mfcol)'and'layout().
I guess that explains the par(ask=TRUE). I'm still interested if anyone can do this using par() and base graphics functions.
I couldn't find any par() variables that would explicitly specify one of the two screens to plot on at any step, while allowing par(ask=T) to update in a subloop, which is what split.screen() was able to do.
Give Hmisc::subplot a try:
## draw first plot
par(mfcol=c(1,2), xpd=NA)
plot(rnorm(3))
plot(1,1) # dummy plot
## update subplot k times
for(k in 1:5) {
rect(grconvertX(par("fin")[1], from="inches"),
grconvertY(0, from="inches"),
grconvertX(par("fin")[1]*2, from="inches"),
grconvertY(par("fin")[2], from="inches"), col="white", border=NA) ## cover-up
subplot( plot(rnorm(3)), 1, 1, size=par("pin") )
readline("Hit <Return> to see next plot: ")
}
Adding a flush.console() and Sys.sleep() should do it.
split.screen(figs=c(1,2),erase=TRUE)
for(j in 1:5){
screen(1)
plot(rnorm(3))
flush.console()
Sys.sleep(0.5)
for(k in 1:5){
screen(2)
plot(rnorm(3))
par(ask=TRUE)
flush.console()
Sys.sleep(0.5)
}
}
That will still suppress the par(ask=TRUE) as per the warnings, but it should prevent the first plot going blank whilst the second iterates.

Resources