# [R] Sweave and Printing Lattice Figures From Loop

Joel Kincaid jfkincaidsu at netscape.net
Fri Jul 25 22:52:44 CEST 2003

Community,

(Windows Xp , 1.7.1, too little memory)

This may have the flavor of an answer in search of a question, but I'll
pose this question: Is their a better way to do the following than what
I'll show below?

Problem:
In Sweave I have multiple figures from lattice, some of which have more
that one page. I can easily figure out the total number of figures I
have created, but its not convient to figure out the number of pages
that would be produced. I'm lazy and do not want to type documentation
chunks for every figure i've created. If all were single page figures,
not a problem, just loop the printing and use some cat() lines to insert
the stuff I dont want to type. However, if some figures are multipage,
this solution breaks down.

Solution:
(note this uses 'list.files()' so may be system dependent..)

Pure R first then
.Snw file after the %%%%%%

library(lattice)
#  produce two figures, first is one page, second is two pages
#   use a naming standard for latter use in eval(parse(..stuff..))
Cond1 <- c("One","Two")
Fig1.1  <- xyplot(rnorm(1:100) ~ rnorm(1:100) | Cond1 )
Cond2 <- c("One","Two","Three","Four")
Fig1.2  <- xyplot(rnorm(1:100) ~ rnorm(1:100) | Cond2 , layout = c(2,1,2))

# loop to construct list of figure names i max * j max = total number of
figures
z <- 1
figureList <- rep("A",2)
for(i in 1:1){
for(j in 1:2){
figureList[z] <- paste("Fig",i,".",j,sep="")
z <- z + 1}}
rm(z)
#   get a list of the files that exist
#   before creating postscripts of figures
#   Note: delete files from previous runs...
fileListOld <-  list.files(getwd())
#   wd needs to be where files are saved!

# number of known figures
NumberFigures   <-  2

for( i in 1:NumberFigures) {

# file=paste("myfile8", i, ".ps", sep="")
#   Note the use of onefile=FALSE--- this allows multiple pages
eval( parse(
file="",
text=paste(
"postscript(file = 'FIG%",
"0",
10-i,       # Note (A)
"d.ps'",
",onefile=FALSE,paper='special',width=11.5,height=8,horizontal=T)",
sep=""
)
)
)
lset(col.whitebg())
eval(parse(file="",text=paste("print(",figureList[i],")")))
#   force print due to lattice
dev.off()
}
#   Now I need to get unknown page counts and file
#   names to output the LaTeX stuff....
fileListNew <-  list.files(getwd())
created <-  fileListNew[!fileListNew%in%fileListOld]
#   use of matching to get list of files not in
#   orginal list
# Note (A)::
#   the usage 10 - i gives files with shorter and shorter
#   file names as you print figures. Thus the
#   list called 'created' is correctly ordered
#   I hve nine known figures in my 'real' Sweave
#   file --- can on anything
#   probably NumberFigures+1 is good

#   The following is used to discove how many
#   pages were produced from the known number of
#   of figures
NumberPages    <-  length(created)
FileNameLength  <-  unlist(lapply(created,nchar))
#   Use this to take advantage of that fact
#   that file names with the same number of
#   characters are pages to a given
UniqueLength    <-  unique(FileNameLength)
#   unique length = base figure count
PagesPerFigure <-  unlist(
lapply(
UniqueLength, function(x) sum(as.numeric(FileNameLength%in%x))
)
)
#   Now that i've produced the
#   figures and indexes
#   need to put in the LaTeX
#   code and proper file names
#   as well as any thing else
z<-1
for(i in 1:NumberFigures){
FigureName <-
for(j in 1:PagesPerFigure[i]){
# this is whats not easy to know before runnning
#   and maybe you want to change condition order...
cat("\\begin{figure}\n")
cat("\\centering\n\n")
cat("\\includegraphics{", created[z], "}\n\n", sep="")
cat("\\caption{ Something Prepended ", figureList[i],"}\n",sep="")
cat("\\end{figure}\n\n")
cat("\\clearpage\n\n") #force floatprocessing in
# LaTeX to  eliminate too many unprocessed floats..
#   see UK FAQ -- 233, 26* and 'FLOATS'
z <- z + 1
}
}
rm(z)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%   .SNW file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%I've set it up so you can just cut and paste in to a latex file

\documentclass{article}
\usepackage{times}
\usepackage{c://mytex//styles//Sweave}
\begin{document}
<<echo=FALSE>>=
library(lattice)
Cond1 <- c("One","Two")
Fig1.1  <- xyplot(rnorm(1:100) ~ rnorm(1:100) | Cond1 )
Cond2 <- c("One","Two","Three","Four")
Fig1.2  <- xyplot(rnorm(1:100) ~ rnorm(1:100) | Cond2 , layout = c(2,1,2))
z <- 1
figureList <- rep("A",2)
for(i in 1:1){
for(j in 1:2){
figureList[z] <- paste("Fig",i,".",j,sep="")
z <- z + 1}}
rm(z)
fileListOld <-  list.files(getwd())
NumberFigures   <-  2
for( i in 1:NumberFigures) {
eval( parse(
file="",
text=paste(
"postscript(file = 'FIG%",
"0",
10-i,       # Note (A)
"d.ps'",
",onefile=FALSE,paper='special',width=11.5,height=8,horizontal=T)",
sep=""
)
)
)
lset(col.whitebg())
eval(parse(file="",text=paste("print(",figureList[i],")")))
dev.off()
}
fileListNew <-  list.files(getwd())
created <-  fileListNew[!fileListNew%in%fileListOld]

NumberPages    <-  length(created)
FileNameLength  <-  unlist(lapply(created,nchar))
UniqueLength    <-  unique(FileNameLength)
PagesPerFigure <-  unlist(
lapply(
UniqueLength, function(x) sum(as.numeric(FileNameLength%in%x))
)
)
@
\section{The Graphs}
<<echo=FALSE,results=tex>>=
z<-1
for(i in 1:NumberFigures){
for(j in 1:PagesPerFigure[i]){
cat("\\begin{figure}\n")
cat("\\centering\n\n")
cat("\\includegraphics{", created[z], "}\n\n", sep="")
cat("\\caption{ Something Prepended ", figureList[i],"}\n",sep="")
cat("\\end{figure}\n\n")
cat("\\clearpage\n\n") #force floatprocessing in
z <- z + 1
}
}
rm(z)
@
\end{document}