I'm posting this for two reasons: one is to see if anyone has a better
way of solving the problem or suggestions for improving my existing
approach; and the other is to show what I'm currently doing in case
anyone else might find it useful.
The background is that I've been using Sweave for several years now to
produce class notes, and I sometimes include quite a lot of raw R input
and output in those notes. My main motivation for doing this is to
demonstrate to the students how to use R to do whatever sort of data
analysis is under discussion, but it seems that the R code and output
often helps to them to grok concepts as well (I was gratified recently
when one of my undergrads said "It's time to see some R code!"
when he
was having trouble understanding something in my lecture on loglinear
models).
Of course, when creating "slides" (e.g., in LaTeX's beamer class),
one
often needs to exert more control over the formatting of R's output than
would otherwise be the case, and having relatively streamlined ways of
doing this can save a lot of very annoying and mind-numbing work. The
main issue I'm interested in here is controlling page breaks for a
verbose command whose output will be spread over several slides. This
comes up most commonly for me with summary(fit), where fit is a fitted
model object, so I will use that as an example, but the same code works
for other things. What I do in such a case is predicated on the notion
that I usaully want page breaks to occur at blank lines in the output,
and beyond that I expect to have to exert some manual control.
My current "solution" is to include near the top of my Rweave file a
code chunk labeled "paragraphs" which I have included at the bottom of
this message. (Of course I also have Sweave's keep.source option set to
TRUE.) Then I do something like the following to spread the
"paragraphs" of output across two slides in this case:
\begin{frame}[containsverbatim,allowframebreaks]
<<>>AC.AM.CM <-
glm(Freq ~ alc*cigs + alc*mj + cigs*mj,
family=poisson, data=teens.df)
@ %def
<<eval=FALSE>>summary(AC.AM.CM)
@ %def
<<echo=FALSE>>tmp <- paragraphs(summary(AC.AM.CM))
tmp[1:2]
@ %def
\break
<<echo=FALSE>>tmp[3:length(tmp)]
@ %def
\end{frame}
The output for this example (Example 7.1.6 of Agresti's "Introduction
to
Categorical Data Analysis") is relatively short, but for more
complicated models such output can spread it over 3 or 4 slides. You
can substitute your own example of course. Here I was trying to show
the students exactly what they would see if they were running this code
themselves, but in other places I might intersperse explanatory text
between the "paragraphs" of output, and I might leave out some
paragraphs altogether; both of these things are easily done in the
obvious way.
So, is this useful to anyone besides me? What trick(s) am I missing
that would make it easier/better, or that would obviate altogether the
need for such manipulations?
Here's the code defining the paragraphs stuff. Suggestions for
improvement are welcome. This was hacked together in desperation a
couple of weeks ago and in the middle of the night, so I don't doubt
that it can be improved.
<<paragraphs,echo=FALSE>>## Something for breaking up long output
into "paragraphs".
paragraphs <- function(x) {
text <- capture.output(x)
blanklines <- (1:length(text))[text == ""]
if (blanklines[1] != 1) blanklines <- c(-1,blanklines)
parstarts <- blanklines + 1
parends <- c(blanklines[-1] - 1, length(text))
npar <- length(parstarts)
res <- list()
for (i in 1:npar) res <- c(res, list(text[parstarts[i]:parends[i]]))
class(res) <- c("paragraphs", res$class)
res
}
as.paragraphs <- paragraphs
assign("[.paragraphs",
function(x, ..., drop = TRUE) {
cl <- oldClass(x)
class(x) <- NULL
val <- NextMethod("[")
class(val) <- cl
val
})
print.paragraphs <- function(x, ...) {
for (i in 1:(length(x))) {
cat(x[[i]], sep="\n")
cat("\n")
}
invisible(x)
}
@ %def
--
Brett Presnell
Department of Statistics
University of Florida