How can automate this section of grid.arrange function in R - r

I have a code chunk that looks like this:
p1 <- plotQC(sce_1, type = "highest-expression")
p2 <- plotQC(sce_2, type = "highest-expression")
p3 <- plotQC(sce_3, type = "highest-expression")
p4 <- plotQC(sce_4, type = "highest-expression")
grid.arrange(p1,p2,p3,p4,ncol=2)
This works very well and has no errors or warnings.
I want to put a loop around. What I have done is
for (i in 1:length(paths))
assign(paste0("p",i), plotQC(get(paste0("sce_",i)), type = "highest-expression"))
grid.arrange(p1,p2,p3,p4,ncol=2)
The second chunk also works very well.However, I would like to make grid.arrange work without manually telling it about p1,p2,p3,p4 but it should detect it the number of p objects.
How can I do this? I am working in R markdown.

If you want to keep with your loop, you could also try this:
p.list <- list()
for (i in 1:length(paths)){
p <- plotQC(get(paste0("sce_",i)), type = "highest-expression")
p.list[[i]] <- p
}
cowplot::plot_grid(plotlist = p.list)
Here, instead of assigning the plot, we save it in a list called p.list, then we build your grid from the list. I used plot_grid from cowplot because it accepts a list of plots as an argument, and I find it easier to work with the plot grid overall.

While all this works, I think you'll agree that the following is better as it in no place requires you to repeat any of the lines or manually specify some numbers:
sce <- list(sce_1, sce_2, sce_3, sce_4)
p <- lapply(sce, plotQC, type = "highest-expression")
do.call(grid.arrange, c(p, ncol = 2))
In particular, working with lists is much better in such cases. For this purpose you probably should produce sce_1, ..., sce_4 also differently, as list elements.

Related

Understanding the duplication of plots in cowplot plot_grid

In desperate need of a sanity check. I am struggling to see why the result of plot_grid (cowplot) of N plots in my code is producing N identical plots. From the list I provide, I've taken out each data frame to verify that each plot should be different, however, when I pass in the complete list to plot_grid they all look identical.
p <- vector("list",length(dataList))
for(i in 1:length(dataList)) {
df <- dataList[[i]]
p[[i]] <- ggplot(df, aes(df$base)) + geom_bar()
}
multi <- plot_grid(plotlist=p, align="hv")
save_plot(paste("data_freqs.tiff",sep=""), multi, dpi=300, base_aspect_ratio=1.5)
For example, when type the following I can see the data is different:
a<-dataList[[1]]
b<-dataList[[2]]
sum(a$base=="T")
>1245
sum(b$base=="T")
>1034
However, I end up with multiple plots of identical T values (all fixed to 1245).
Any help is much appreciated.
Thanks

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)

Generate list of R plotly plots and pass it to subplot

I usually generate subplots in a for loop when using base R graphics (using par(mfrow=c(nr,nc))). I'm trying to do something similar with plotly, by generating a series of plots and saving them to a list to be later passed to the subplot function. However, for reasons that I don't understand, at the end of the loop all the elements of the list seem to contain the same plot (the last one). If I print each plot in the list within the loop (uncommenting the line starting with print in the example below), then the plots seem fine). I don't really understand what's going on. Could someone explain this unexpected behavior or point out issues with my example code below?
library(plotly)
plotList = list()
plotListNames = c("p1", "p2", "p3")
for (i in 1:3){
x = rnorm(10)
y = rnorm(10)
thisName = plotListNames[i]
plotList[[thisName]] = plot_ly(x=x,y=y, name=thisName)
##print(plotList[[thisName]]
}
sbp = subplot(plotList[["p1"]], plotList[["p2"]], plotList[["p3"]])
print(sbp)
try this:
plotList[[thisName]] = plotly_build(plot_ly(x=x,y=y, name=thisName))

ggplot2 : printing multiple plots in one page with a loop

I have several subjects for which I need to generate a plot, as I have many subjects I'd like to have several plots in one page rather than one figure for subject.
Here it is what I have done so far:
Read txt file with subjects name
subjs <- scan ("ListSubjs.txt", what = "")
Create a list to hold plot objects
pltList <- list()
for(s in 1:length(subjs))
{
setwd(file.path("C:/Users/", subjs[[s]])) #load subj directory
ifile=paste("Co","data.txt",sep="",collapse=NULL) #Read subj file
dat = read.table(ifile)
dat <- unlist(dat, use.names = FALSE) #make dat usable for ggplot2
df <- data.frame(dat)
pltList[[s]]<- print(ggplot( df, aes(x=dat)) + #save each plot with unique name
geom_histogram(binwidth=.01, colour="cyan", fill="cyan") +
geom_vline(aes(xintercept=0), # Ignore NA values for mean
color="red", linetype="dashed", size=1)+
xlab(paste("Co_data", subjs[[s]] , sep=" ",collapse=NULL)))
}
At this point I can display the single plots for example by
print (pltList[1]) #will print first plot
print(pltList[2]) # will print second plot
I d like to have a solution by which several plots are displayed in the same page, I 've tried something along the lines of previous posts but I don't manage to make it work
for example:
for (p in seq(length(pltList))) {
do.call("grid.arrange", pltList[[p]])
}
gives me the following error
Error in arrangeGrob(..., as.table = as.table, clip = clip, main = main, :
input must be grobs!
I can use more basic graphing features, but I d like to achieve this by using ggplot. Many thanks for consideration
Matilde
Your error comes from indexing a list with [[:
consider
pl = list(qplot(1,1), qplot(2,2))
pl[[1]] returns the first plot, but do.call expects a list of arguments. You could do it with, do.call(grid.arrange, pl[1]) (no error), but that's probably not what you want (it arranges one plot on the page, there's little point in doing that). Presumably you wanted all plots,
grid.arrange(grobs = pl)
or, equivalently,
do.call(grid.arrange, pl)
If you want a selection of this list, use [,
grid.arrange(grobs = pl[1:2])
do.call(grid.arrange, pl[1:2])
Further parameters can be passed trivially with the first syntax; with do.call care must be taken to make sure the list is in the correct form,
grid.arrange(grobs = pl[1:2], ncol=3, top=textGrob("title"))
do.call(grid.arrange, c(pl[1:2], list(ncol=3, top=textGrob("title"))))
library(gridExtra) # for grid.arrange
library(grid)
grid.arrange(pltList[[1]], pltList[[2]], pltList[[3]], pltList[[4]], ncol = 2, main = "Whatever") # say you have 4 plots
OR,
do.call(grid.arrange,pltList)
I wish I had enough reputation to comment instead of answer, but anyway you can use the following solution to get it work.
I would do exactly what you did to get the pltList, then use the multiplot function from this recipe. Note that you will need to specify the number of columns. For example, if you want to plot all plots in the list into two columns, you can do this:
print(multiplot(plotlist=pltList, cols=2))

Assigning "beanplot" object to variable in R

I have found that the beanplot is the best way to represent my data. I want to look at multiple beanplots together to visualize my data. Each of my plots contains 3 variables, so each one looks something like what would be generated by this code:
library(beanplot)
a <- rnorm(100)
b <- rnorm(100)
c <- rnorm(100)
beanplot(a, b ,c ,ylim = c(-4, 4), main = "Beanplot",
col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6")
(Would have just included an image but my reputation score is not high enough, sorry)
I have 421 of these that I want to put into one long PDF (EDIT: One plot per page is fine, this was just poor wording on my part). The approach I have taken was to first generate the beanplots in a for loop and store them in a list at each iteration. Then I will use the multiplot function (from the R Cookbook page on multiplot) to display all of my plots on one long column so I can begin my analysis.
The problem is that the beanplot function does not appear to be set up to assign plot objects as a variable. Example:
library(beanplot)
a <- rnorm(100)
b <- rnorm(100)
plot1 <- beanplot(a, b, ylim = c(-5,5), main = "Beanplot",
col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6")
plot1
If you then type plot1 into the R console, you will get back two of the plot parameters but not the plot itself. This means that when I store the plots in the list, I am unable to graph them with multiplot. It will simply return the plot parameters and a blank plot.
This behavior does not seem to be the case with qplot for example which will return a plot when you recall the stored plot. Example:
library(ggplot2)
a <- rnorm(100)
b <- rnorm(100)
plot2 <- qplot(a,b)
plot2
There is no equivalent to the beanplot that I know of in ggplot. Is there some sort of workaround I can use for this issue?
Thank you.
You can simply open a PDF device with pdf() and keep the default parameter onefile=TRUE. Then call all your beanplot()s, one after the other. They will all be in one PDF document, each one on a separate page. See here.

Resources