How to remove first blank page when lapply is used? - r

I have a simple question. When we would like to remove the first blank page for an individual plot, we set
pdf("abc.pdf", onefile=FALSE)
However, when we are plotting using lapply, setting onefile=FALSE will only print the last plot.
I wonder how we solve this? Thanks!

When I tried this code on a Linux box running R 4.0.4 it produced five one page pdf files:
for(i in 1:5){ pdf(file=paste0("x",i, '.pdf')); plot(1,1); dev.off()}
If this doesn't succeed on your setup, then you need to describe it better.
I then tried for completeness:
lapply(1:5, function(y){pdf(file=paste0("xx",y, '.pdf')); plot(1,1); dev.off() })
# same results

Related

Why am I unable to see multiple plots appear with a for loop?

This is my code which is part of a larger script.
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
png(paste(survPath,"/surv_",d1,".png",sep=""))
plot(survfit1,xlab="Years",ylab="Survival probability",xmax=xmax1)
}
I don't have a good idea of what this code does yet, so I'm trying to look at each individual plot to see what it is. The problem is, whenever I run this in the R command line in the terminal in linux, nothing appears. I have to use dev.off() multiple times and then rerun this code:
plot(survfit1)
for something to appear. How can I see all the plots?
Sounds like this is really what you want:
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
x11() ## open up new graphical window for each plot (to avoid overwriting)
plot(survfit1,xlab="Years",ylab="Survival probability",
xmax=xmax1, main = d1) ## use different titles to distinguish those plots
}
This will produce plots on normal graphical windows.
If you want to use the original code, you'd better do this way:
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
png(paste(survPath,"/surv_",d1,".png",sep=""))
plot(survfit1,xlab="Years",ylab="Survival probability",xmax=xmax1)
dev.off()
}
Then, have a look at the directory given by getwd(). All the plots are saved in png files.
Calling Sys.sleep(.1) might help during the for loop. Maybe try:
for(d1 in names(survD)){
survfit1 <- survfit(Surv(time=survD[[d1]][,"time"],
event=survD[[d1]][,"death"],type='right')~1)
Sys.sleep(.1)
png(paste(survPath,"/surv_",d1,".png",sep="", collapse="))
plot(survfit1,xlab="Years",ylab="Survival probability",xmax=xmax1)
dev.off()
}

how do you print ggplot output inside a for loop in sweave [duplicate]

My chunk in Sweave:
<<fig=TRUE,echo=FALSE>>=
for(i in 1:10) {
plot(rep(i,10))
dev.new()
}
#
In the resulting pdf I get only one plot (from the first iteration). I would like to have all of the 10 plots printed. What am I doing wrong? I tried replacing dev.new() with frame() and plot.new() but nothing happened.
As #rawr suggests the easiest solution is to switch to knitr (there's really no reason at all not to!) and put fig.keep="all" in your code chunk options (if you switch to knitr you don't need fig=TRUE any more ... including figures works automatically, fig.keep="none" is the analogue of fig=FALSE)
Alternatively, if you want to stick with vanilla Sweave, check the Sweave manual p. 17:
A.9 Creating several figures from one figure chunk does not work
Consider that you want to create several graphs in a loop similar to
<<fig=TRUE>>
for (i in 1:4) plot(rnorm(100)+i)
#
This will currently not work, because Sweave allows only one graph per figure chunk. The simple reason is that Sweave opens a postscript device before executing the code and closes it
afterwards. If you need to plot in a loop, you have to program it along the lines of
<<results=tex,echo=FALSE>>=
for(i in 1:4){
file=paste("myfile", i, ".eps", sep="")
postscript(file=file, paper="special", width=6, height=6)
plot(rnorm(100)+i)
dev.off()
cat("\\includegraphics{", file, "}\n\n", sep="")
}
#

Multiple plots in a for loop with Sweave

My chunk in Sweave:
<<fig=TRUE,echo=FALSE>>=
for(i in 1:10) {
plot(rep(i,10))
dev.new()
}
#
In the resulting pdf I get only one plot (from the first iteration). I would like to have all of the 10 plots printed. What am I doing wrong? I tried replacing dev.new() with frame() and plot.new() but nothing happened.
As #rawr suggests the easiest solution is to switch to knitr (there's really no reason at all not to!) and put fig.keep="all" in your code chunk options (if you switch to knitr you don't need fig=TRUE any more ... including figures works automatically, fig.keep="none" is the analogue of fig=FALSE)
Alternatively, if you want to stick with vanilla Sweave, check the Sweave manual p. 17:
A.9 Creating several figures from one figure chunk does not work
Consider that you want to create several graphs in a loop similar to
<<fig=TRUE>>
for (i in 1:4) plot(rnorm(100)+i)
#
This will currently not work, because Sweave allows only one graph per figure chunk. The simple reason is that Sweave opens a postscript device before executing the code and closes it
afterwards. If you need to plot in a loop, you have to program it along the lines of
<<results=tex,echo=FALSE>>=
for(i in 1:4){
file=paste("myfile", i, ".eps", sep="")
postscript(file=file, paper="special", width=6, height=6)
plot(rnorm(100)+i)
dev.off()
cat("\\includegraphics{", file, "}\n\n", sep="")
}
#

Generating beanplots in a forloop with LaTeX

I am trying to automatically generate a number of beanplots with a forloop, and outputting them into a LaTeX document. Starting with a data frame (that successfully generates beanplots), I am using the code below. The intent is to output consecutive beanplots into the document. I am able to do this by writing a beanplot command for each desired plot (it works fine), but obviously this would be much nicer if I could do it with a forloop. However, when I try to use a forloop, instead of outputting say 9 plots, it only outputs the last plot. Any ideas on why this is? I tried using fig.keep='all' and plot.new(), neither helped. Compiling with Sweave. Thanks!
<<beanplots,fig.keep='all'>>=
#fig.keep='all' <- this did not help
suppressPackageStartupMessages(require(beanplot))
for (i in length(unique(Data[['Days']]))){
# plot.new() ## this did not help either
beanplot(Readings~FactorLevels,
data=subset(x=Data, subset=(Data[['Days']]==i)),
main=paste("Day",i,sep=" "),
cex.axis=0.7)
}
#
beanplot works with the Lattice graphics library. As such, it does not automatically produce plots when running non-interactively. You must explicitly call print() on the object returned by the call to produce a plot. Try
<<beanplots,fig.keep='all'>>=
#fig.keep='all' <- this did not help
suppressPackageStartupMessages(require(beanplot))
for (i in unique(Data[['Days']])){
# plot.new() ## this did not help either
print(beanplot(Readings~FactorLevels,
data=subset(x=Data, subset=(Data[['Days']]==i)),
main=paste("Day",i,sep=" "),
cex.axis=0.7))
}
#

Save ggplot within a function

I'm trying to save a ggplot within a function using graphics devices. But I found the code produces empty graphs. Below is a very very simple example.
library(ggplot2)
ff <- function(){
jpeg("a.jpg")
qplot(1:20, 1:20)
dev.off()
}
ff()
If I only run the content of the function, everything is fine. I know that using ggsave() will do the thing that I want, but I am just wondering why jpeg() plus dev.off() doesn't work. I tried this with different versions of R, and the problem persists.
You should use ggsave instead of the jpeg(); print(p); dev.off() sequence. ggsave is a wrapper that does exactly what you intend to do with your function, except that it offers more options and versatility. You can specify the type of output explicitly, e.g. jpg or pdf, or it will guess from your filename extension.
So your code might become something like:
p <- qplot(1:20, 1:20)
ggsave(filename="a.jpg", plot=p)
See ?ggsave for more details
The reason why the original behaviour in your code doesn't worked is indeed a frequently asked question (on stackoverlflow as well as the R FAQs on CRAN). You need to insert a print statement to print the plot. In the interactive console, the print is silently execututed in the background.
These plots have to be printed:
ff <- function(){
jpeg("a.jpg")
p <- qplot(1:20, 1:20)
print(p)
dev.off()
}
ff()
This is a very common mistake.

Resources