ggforce facet_wrap_paginate with number of plots not matching nrow and ncol - facet-wrap

I have a problem with the facet_wrap_paginate function: I have several groups of diagrams. The number of diagrams in each group varies. When I use facet_wrap_paginate to plot each group in 5x4 diagrams onto one single pdf, I get an error if the last pdf page has too few plots, so that the first row of plots is not "filled".
e.g. one group of plots contains 22 plots, so 20 plots go on the first page and the second page only has 2 plots, which leads to an error :
Error: Cannot create zero-length unit vector ("unit" subsetting)
This is the example code:
for (i in Classes)
{
x <- filter(all_data_R2_filtered, class.x== "i" )
bp <- ggplot(data = x, aes(x=dil, y=mmol, color=AcquiMeth))+
geom_point()+
facet_wrap_paginate(name.x ~ ., ncol = 5, nrow = 4, scales = "free")
number_of_pages <- n_pages(bp)
pdf(paste("class",i,".pdf", sep = ""), paper= 'A4r', w= 297, h= 210)
for(j in 1:number_of_pages){
print(bp + facet_wrap_paginate(name.x ~ . , ncol = 5, nrow = 4, page = j))
}
dev.off()
}
Is there a fix for this? Thanks a lot in advance for your help

Related

How to save output from ggforce::facet_grid_paginate in only one pdf?

I'm using the ggforce package to generate facetted plots over several pages:
library(ggforce)
for(i in 1:6){
ggplot(diamonds) +
geom_point(aes(carat, price), alpha = 0.1) +
facet_wrap_paginate(~cut:clarity, ncol = 2, nrow = 2, page = i)
ggsave(paste0("~/diamonds_", i, ".pdf"))
}
which is generating the expected 6 PDF files:
What is the easiest way have the output in one single pdf with 6 pages?
I understand this can be done with the reports and pdftools packages, but I'm wondering if there's a more direct way to accomplish this. I'd expect ggforce to provide the functionality for the output to be single-paged, but it looks like that's not the case?
You don't even need to use ggsave you can put all these plots into one pdf by:
pdf("~/diamonds_all.pdf")
for(i in 1:6){
print(ggplot(diamonds) +
geom_point(aes(carat, price), alpha = 0.1) +
facet_wrap_paginate(~cut:clarity, ncol = 2, nrow = 2, page = i))
}
dev.off()
I'm facing a similar question and here's my solution, basically an extension of Mike H. answer.
Typically you want to plot all the pages and you don't know beforehand how many pages you have, also, you may want to print on standard A4 size paper. So:
library(ggforce)
gg <- ggplot(diamonds) +
geom_point(aes(carat, price)) +
facet_wrap_paginate(~cut:clarity, ncol = 2, nrow = 2, page = 1)
n <- n_pages(gg)
pdf('diamonds.pdf', paper= 'A4', w= 210/25.4, 297/25.4)
for(i in 1:n){
print(gg + facet_wrap_paginate(~cut:clarity, ncol = 2, nrow = 2, page = i))
}
dev.off()
Code should be self-explanatory. The ugly thing is that you have to repeat facet_wrap_paginate(...) twice or wrap it into a dedicated function. I'd like to hear of a better solution...

marrangeGrob giving error for nrow

I'm trying to create a bunch of ggplot2 plots using a for loop and then saving them on a multi-page pdf document, and I'm having trouble with marrangeGrob. Here's some example code:
Plots <- list()
Plots[[1]] <- qplot(mtcars$mpg, mtcars$wt)
Plots[[2]] <- qplot(mtcars$cyl, mtcars$wt)
Plots[[3]] <- qplot(mtcars$mpg, mtcars$qsec)
Plots[[4]] <- qplot(mtcars$cyl, mtcars$drat)
# install.packages("gridExtra", dependencies = TRUE)
library(gridExtra)
MyPlots <- do.call(marrangeGrob, c(Plots, nrow = 1, ncol = 2))
ggsave("My plots on multiple pages.pdf", MyPlots)
I've used similar versions of the do.call(marrangeGrob... line in the past and had them work, but now, I get this error when I try to execute that line: Error: nrow * ncol >= n is not TRUE. The fact that code similar to this used to work makes me think that something in one of these packages has since been updated. Any suggestions on how to fix this?
The syntax has changed a little with the new grobs argument. You should use
marrangeGrob(grobs=Plots, nrow = 1, ncol = 2)
or, equivalently,
do.call(marrangeGrob, list(grobs=Plots, nrow = 1, ncol = 2))

Adding barplots around heatmap using R

My problem is different from this Side-by-side plots with ggplot2.
Two reasons: 1) With aheatmap() function, the heatmap by aheatmap() and barplots by other functions cann't save in one picture when i use gridExtra.
2) I want "barplots correspond to the rows/columns of the heatmap". I have tried with gridExtra, but the picture changed with the different data sets.
I want to merge some barplots with a heatmap, such that a left/right barplot correspond to the rows of the heatmap, and further that a top/bottom barplot correspond to the columns of the heatmap.
Like this picture (and a barplot in the bottom)
MATLAB Bar graph + HeatMap/Imagesc
Now the aheatmap() in NMF package is used and the code as followings (but I
cann't add barplots):
n <- 50; p <- 20
x <- abs(rmatrix(n, p, rnorm, mean=4, sd=1))
x[1:10, seq(1, 10, 2)] <- x[1:10, seq(1, 10, 2)] + 3
x[11:20, seq(2, 10, 2)] <- x[11:20, seq(2, 10, 2)] + 2
rownames(x) <- paste("ROW", 1:n)
colnames(x) <- paste("COL", 1:p)
annotation = data.frame(Var1 = factor(1:p %% 2 == 0, labels = c("Class1", "Class2")), Var2 = 1:10)
aheatmap(x, annCol = annotation, Rowv=FALSE)
Any suggestions to add barplots using aheatmap() or even using other packages?
What about something along these lines to begin with?
m <- matrix(abs(rnorm(25 * 10)), ncol = 25)
plotMyHeat <- function(x) {
x <- t(x)
l <- matrix(c(1,2), ncol = 2)
layout(l)
op <- par(mar = c(2,2,1,0))
image(x)
par(mar = c(2,1,1,1))
barplot(rowMeans(x),horiz = TRUE, yaxs = "i")
par(op)
}
plotMyHeat(m)

My code doesn't work... How do I make a grid in pdf output in R?

I am scratching my head for the following code.
I am following this example:
How can I arrange an arbitrary number of ggplots using grid.arrange?
I wanted to collect the plots and lay them out on a 3x9 grid and each grid with suitable labels...
But it doesn't work. The pdf generated is still one-plot-per-page - so there are 27 pages generated.
I am trying to use "grid.arrange", however, the function "plotFunctionWrittenByOtherPeople" was written by other people, and it doesn't return a handle to the plot... and it's quite complicated.
How to arrange the plots nicely?
Could anybody please shed some lights on this?
Thanks a lot!
pdf("mytry1.pdf", width = 11, height = 8.5)
par(mfrow=c(3, 9))
for (a in seq(100, 900, by=100))
for (b in c(1, 3, 6))
{
plotFunctionWrittenByOtherPeople(a, b)
}
dev.off()
I think that you want to create a grid layout of a bunch of plots created by ggplot2. Unfortunately, par(mfrow=) is a base graphics function that doesn't work with ggplot2. Use grid.arrange in the gridExtra package.
library(ggplot2)
library(gridExtra)
# Completely fake plotting function.
makePlot = function(a, b) {
dat = data.frame(x=rnorm(a), y=rnorm(a))
p = ggplot(dat, aes(x=x, y=y)) +
geom_point(size=b, alpha=1/b) +
opts(title=paste("a = ", a, ", b = ", b, sep="")) +
opts(plot.title=theme_text(size=12))
return(p)
}
plot_list = list() # Create an empty list to hold plots.
for (b in c(1, 3, 6)) { # I switched a and b loops
for (a in seq(100, 900, by=100)) { # to make the final layout neater.
p = makePlot(a, b)
plot_list = c(plot_list, list(p)) # Add new plot to list.
}
}
pdf("mytry1.pdf", width = 14, height = 6)
do.call(grid.arrange, c(plot_list, list(nrow=3, ncol=9, main="Grid of Plots")))
dev.off()
Edit: Can this be made more concise?
The plot_list can be created and output to pdf much more compactly. Thanks to #baptiste for suggesting mlply, ggsave and arrangeGrob.
library(plyr)
plot_list = mlply(expand.grid(a=seq(100, 900, by=100), b=c(1, 3, 6)), makePlot)
ggsave(filename="grid_1.pdf", height=6, width=14,
plot=do.call(arrangeGrob, c(plot_list, nrow=3, main="Grid of Plots")))

R problem with multiple plots pdf win7

I am trying to make one figure by stacking two graphs (a) and (b) vertically (i.e., a multiple plot with 2 rows, 1 column).
While I can do this for other plots I have tried, the following two plots generated from data using the ODE solver package deSolve refuse to be combined. On the screen, plot (a) flashes by and I am left looking at plot (b). Saving the plots results in 1 pdf file with 2 pages (each plot on a separate page) rather than 1 pdf file and 1 page (with both plots stacked into one figure as I am seeking).
As you can see from the code I have tried both mfrow and layout approaches to no avail. Any help would be greatly appreciated.
Thanks,
Carey
df1 <-function(t,y,mu)( list(c(y[2], mu*y[1]^3 - y[1] + 0.005 * cos(t))))
library(deSolve)
yini <- c(y1=0, y2=0)
df2 <-ode(y = yini, func = df1, times = 0:1050, parms = 0.1667)
t <- seq(0, 1050, length=10000)
x <- 0.24 * (1 - cos(0.012 * t)) * cos(t + sin(0.012 * t))
pdf("c:/users/name/Desktop/figure2.pdf", height = 3, width=8)
# par(mfrow = c(2, 1))
layout(matrix(c(1, 2), 2, 1, byrow = TRUE))
plot(df2, type="l", which="y1", ylab="x", xlab="t", main="(a)")
plot(t, x, type="l", main="(b)")
dev.off()
The problem is that deSolve objects have their own plot method, and that overrides what happens with layout. As soon as your first plot is run, the layout set up is completely undone and the display is configured in terms of the defaults for deSolve objects. That's why there's a flash when the second plot writes over the first since there is no longer a multi-panel display.
The plot method is ?plot.deSolve - this function takes mfrow/mfcol arguments, so you can work with your layout as intended.
layout(matrix(c(1, 1, 2, 2), 2, 2, byrow = TRUE))
plot(df2, type="l", which = "y1", ylab = "x", xlab = "t", main = "(a)", mfrow = c(2, 1))
plot(t, x, type = "l", main = "(b)")

Resources