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

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?

Related

Plot Layout of Base R Plots Saved by recordPlot() Function

I can use the recordPlot() function to save Base R plots in data objects:
plot(1:5, 1:5)
my_plot1 <- recordPlot()
plot(1:10, 1:10)
my_plot2 <- recordPlot()
plot(1:20, 1:20)
my_plot3 <- recordPlot()
I would like to draw these three plots in a grid of plots. Usually, I could use the layout function for this. However, this does not work when I want to draw plots created by recordPlot.
This does not work:
layout(matrix(c(1, 0, 2, 3), ncol = 2))
plot.new()
my_plot1
my_plot2
my_plot3
How can I draw a grid of plots saved by the recordPlot() function?
I recently had to solve a similar problem, below are two solutions that may work for you.
(1) use par() to specify numbers of rows/ columns:
# create objects with base plots
plot(rnorm(50),rnorm(50))
my_plot1 <- recordPlot()
plot(rnorm(50),rnorm(50))
my_plot2 <- recordPlot()
plot(rnorm(50),rnorm(50))
my_plot3 <- recordPlot()
# clear plots in workspace
plot.new()
# plot side by side
par(mfrow= c(1,3)) # specify rows (1) and columns (3) for plotting
my_plot1
my_plot2
my_plot3
(2) Save objects to a list and then use plot_grid (cowplot library) - this is good if you need to export the figure:
library(cowplot)
# create empty list
p <- list()
# save objects to list
plot(rnorm(50),rnorm(50))
p[[1]] <- recordPlot()
plot(rnorm(50),rnorm(50))
p[[2]] <- recordPlot()
plot(rnorm(50),rnorm(50))
p[[3]] <- recordPlot()
# clear plots
plot.new()
# plot in 3 columns using plot_grid
plot_grid(plotlist = p, nrow=1, ncol=3)

arrange R plots: how can I arrange plots of the VIM package?

I would like to generate multiple plots using marginplot() (VIM package) and then arrange them into one big figure. I tried to use grid.arrange (grid/gridExtra package) and it did not work. The error was, that a grob was expected as input. So I tried to first convert the marginplot into a ggplot (as.ggplot) or grob (as.grob) but this did not work. Has anyone an idea how to arrange the plots?
library(VIM)
library(ggplotify)
library(grid)
library(gridExtra)
x <- cars[, c("speed", "dist")]
marginplot(x)
y <- cars[, c("speed", "dist")]
marginplot(y)
p <- qplot(1,1)
#p2 <- as.ggplot(marginplot(x))
r <- rectGrob(gp=gpar(fill="grey90"))
grid.arrange( r, p,p, r, ncol=2)
I created a small code with cars, where I managed to arrange grey squares and qplots. put I cannot add the marginplot.
With base plots this error occurs. Learned here: grid.arrange from gridExtras exiting with "only 'grobs' allowed in 'gList'" after update
grid.arrange is intended to be used with "grid graphical objects" (grobs), such as ggplot2.
One could find an equivalent grid-plot or use a base-graphics approach to stacking plots.
Try this:
library(VIM)
x <- cars[, c("speed", "dist")]
y <- cars[, c("speed", "dist")]
par(mfrow = c(2,2))
marginplot(x)
marginplot(y)
plot(rnorm(100))
hist(rnorm(100))
par(mfrow = c(1, 1)) #reset this parameter

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.

Multiple graphs within plot with loop

How to get graph for each column of data.frame within one plot with loop? Must be easy just can't figure it out.
Sample data:
rdata <- data.frame(y=rnorm(1000,2,2),v1=rnorm(1000,1,1),v2=rnorm(1000,3,3),
v3=rnorm(1000,4,4),v4=rnorm(1000,5,5))
What I have tried?
library(lattice)
p <- par(mfrow=c(2,2))
for(i in 2:5){
w <- xyplot(y~rdata[,i],rdata)
print(w)
}
par(p)
If you don't have to use lattice you can just use base plot instead and it should work as you want.
p <- par(mfrow=c(2,2))
for(i in 2:5){
plot(y~rdata[,i],rdata)
}
par(p)
If you want to use lattice look this answer. Lattice ignores par, so you have to do some more work to achieve what you want.
Inorder to easily arrange a bunch of lattice plots, I like to use the helper function print.plotlist. It has a layout= parameter that acts like the layout() function for base graphics. For example, you could call
rdata <- data.frame(y=rnorm(1000,2,2),v1=rnorm(1000,1,1),v2=rnorm(1000,3,3),
v3=rnorm(1000,4,4),v4=rnorm(1000,5,5))
library(lattice)
plots<-lapply(2:5, function(i) {xyplot(y~rdata[,i],rdata)})
print.plotlist(plots, layout=matrix(1:4, ncol=2))
to get
Otherwise you normally use a split= parameter to the print statement to place a plot in a subsection of the device. For example, you could also do
print(plots[[1]], split=c(1,1,2,2), more=T)
print(plots[[2]], split=c(1,2,2,2), more=T)
print(plots[[3]], split=c(2,1,2,2), more=T)
print(plots[[4]], split=c(2,2,2,2))

Multiple lattice plots with gridExtra

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

Resources