How to capture R text+image output into one file (html, doc, pdf etc)?

17,637

Solution 1

As of 2012 knitr provides a perfect solution to this problem.

For example, create a file with an rmd extension. Wrap your code in a couple of commands as follows:

```{r}
x <- rnorm(100)
y <- jitter(x)
print(summary(x))
print(head(data.frame(x,y)))
cor(x,y)
plot(x,y)
print(summary(lm(y~x)))
```

You can convert it into a self-contained HTML file in several ways. In RStudio you just press a single button Knit HTML. This is the HTML file produced; to actually view how the HTML displays in a browser, save the file and open it.

Images code, and output are interweaved as you might expect.

Of course, you can and typically would divide up your file into multiple R code chunks. But the point is, you don't have to.

Here are another couple of examples I've created:

Solution 2

I would encourage you to use Sweave, but a rudimentary functionality that is not pretty can be achieved with sink().

A regular txt file:

sink(file = "test.txt", type = "output")
summary(cars)
sink()

or add some HTML tags:

sink(file = "tal_test.html", type = "output")
cat("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"", "\n")
cat("\"http://www.w3.org/TR/html4/strict.dtd\">", "\n")
        cat("<HTML>", "\n")
        cat("<HEAD>", "\n")
        cat("<TITLE>My first HTML document</TITLE>", "\n")
        cat("</HEAD>", "\n")
        cat("<BODY>", "\n")
        summary(cars)
        cat("</BODY>", "\n")
        cat("</HTML>", "\n")
sink()

Solution 3

If you know LaTeX, sweave will likely be your best bet. odfWeave is a similar mechanism but for embedding the code in an OpenOffice.org file. For HTML there is the R2html package. But all will likely require you to break the code up a little bit to get the best out of the systems. Alternatively, your sweave/odfweave/html template could source the data generation aspects of the script in a single code chunk, with the output display (print() statements) placed where required. Your graphics could also be called within the script to produce the figures to embed in the document as separate files, which you then include by hand in the template.

For example (and this isn't a full .Rnw file for running through sweave) in a sweave file you'd put something like this high up in the template which sources the main part of the R script that will do the analysis and generate the R objects:

<<run_script, eval=TRUE, echo=FALSE, results=hide>>=
source("my_script.R")
@

Then you will need to insert code chunks where you want printed output:

<<disp_output, eval=TRUE, echo=FALSE, results=verbatim>>=
## The results=verbatim is redundant as it is the default, as is eval=TRUE
print(summary(x)) ## etc
@

Then you will need chunks to insert the figures.

Separating your analysis code from the output (printed and/or figures) is probably good practice as well, especially if the analysis code is expensive in compute terms. You can run it once - or even cache it - whilst updating the output/display code as you need to.

Example Sweave File

Using csgillespie's example sweave file I would set things up like this. First the my_script.R file containing the core analysis code:

x <- rnorm(100)
y <- jitter(x)
corXY <- cor(x,y)
mod.lm <- lm(y~x)

Then the Sweave file

\documentclass[12pt]{article}
\usepackage{Sweave}
\begin{document}

An introduction
<<run_analysis, eval=TRUE,echo=FALSE, results=hide>>=
source("my_script.R")
@

% Later
Here are the results of the analysis
<<show_printed_output, echo=FALSE>>=
summary(x))
head(data.frame(x,y))
@

The correlation between \texttt{x} and \texttt{y} is:
<<print_cor, echo=FALSE>>=
corXY
@

Now a plot
\begin{figure}[h]
    \centering
<<echo=FALSE, eval=TRUE, fig=TRUE, width=6, height=4>>=
plot(x,y)
@ 
\caption{\textit{A nice plot.}}
\end{figure}

\end{document}

What you seem to be wanting doesn't exist; a simple way of combining R code and output into a document file. That is if you don't consider sweave and its ilk simple. You might need to rethink what you want to do or how you arrange your analysis and graphics and output code, but you are likely best served looking at one of the suggested options (sweave, odfweave, brew, R2html).

HTH

Solution 4

You can use the R2HTML package to output a session to html and there are some similar functions in the TeachingDemos package (see txtStart) for output to enhanced text and word (via R2wd). Non-graphics commands will be included in the file automatically and the current plot can be inserted by a single command.

Solution 5

You mentioned sweave in your question but not really why it isn't suitable. Your question seems perfect for Sweave. In fact, your example code could have came from the second Sweave example.

Example Sweave file

If you know Latex then Sweave isn't that difficult. Here's your example file as a Sweave file:

\documentclass[12pt,BCOR3mm,DIV16]{scrreprt}
\usepackage{Sweave}
\begin{document}

An introduction
<<eval=TRUE,echo=TRUE>>=
x <- rnorm(100)
y <- jitter(x)
print(summary(x))
print(head(data.frame(x,y)))
cor(x,y)
@ 
Now a plot
\setkeys{Gin}{width=0.5\textwidth}
\begin{figure}[h]
    \centering
<<echo=FALSE, eval=TRUE, fig=TRUE, width=6, height=4>>=
plot(x,y)
@ 
\caption{\textit{A nice plot.}}
\end{figure}

\end{document}

Under linux, just save the file as tmp.Rnw. Then

R CMD Sweave tmp.Rnw
pdflatex tmp.tex
Share:
17,637
Tal Galili
Author by

Tal Galili

Statistics, blogging, and the hope for a happy long life.

Updated on June 13, 2022

Comments

  • Tal Galili
    Tal Galili almost 2 years

    The task is to create a file (word, rtf, pdf, html, or whatever) that will capture the output of R (e.g: not the code that created the output), into that format (including text and images).

    The way of doing this should involve as little change to the original R script as possible.

    If I had cared only for the text or images, then I would use ?sink, or ?pdf. But I don't know how to combine the two into one output in an easy way.

    I know there is a way to export R output using r2wd, but it involves too much medaling in the original code for my taste (I imagine the same is true for the sweave solution, although I don't have experience with it to tell)

    Here is a sample code for future examples:

    START.text.and.image.recording("output.file") # this is the function I am looking for
    x <- rnorm(100)
    y <- jitter(x)
    print(summary(x))
    print(head(data.frame(x,y)))
    cor(x,y)
    plot(x,y)
    print(summary(lm(y~x)))
    STOP.text.and.image.recording("output.file") # this is the function I am looking for
    

    Update: I was asked way not Sweave, or other options from ReproducibleResearch task view.

    The reasons are:

    1. I don't (yet) know LaTeX
    2. Even knowing LaTeX, I want something with simple defaults to simply dump all the outputs together, and in order. "simply" means - as little extra code/file management overhead as possible.

    I understand that something like sweave or brew are more scalable, but I am looking to see if there is a more "simple" solution for smaller projects/scripts.

  • Tal Galili
    Tal Galili over 13 years
    Hi csgillespie, the code for the example you gave has a lot of "before and after" additions to the code (stat.uni-muenchen.de/~leisch/Sweave/example-2.Snw) including the fact that I will need to learn (some) latex+sweave. Which is something to do one day, but I am looking if there is a simpler alternative.
  • chl
    chl over 13 years
    @Tal I'll add to @csgillespie odfSweave and brew (probably less flexible). Check out also Sweave and LaTeX, j.mp/dah7Hr.
  • chl
    chl over 13 years
    @Tal I guess you can always write some code (Python, Ruby or whatever) to store R output in temp file, as well as images, calling R in BATCH mode, and then compile all of them in a tex file after inserting the temp files. Actually, this is what is done for embedding R code in ConTeXt file.
  • chl
    chl over 13 years
    @Tal Huh, I browse through your r2wd example: it's awful (ok, I never use Micro$oft tools, and my appreciation is certainly biased)! I'm sure there's a better way to handle this with Python scripting and tex/html export... Just to call for other responses...
  • Jeromy Anglim
    Jeromy Anglim over 13 years
    How would images be automatically included?
  • Tal Galili
    Tal Galili over 13 years
    Hi mbq, do you mean to wrap every line of code, or to wrap the entire section ?
  • mbq
    mbq over 13 years
    @Tal Rather a custom print and plot that formats ans redirect their output to the report file. R does not have any output handler to hook to :-(
  • chl
    chl over 13 years
    @mbq Isn't this close to what R2HTML actually does (more or less)?
  • mbq
    mbq over 13 years
    @chl R2HTML is R object to HTML converter, Tal wanted to capture textual output and images only, to, as I understand, make something like static Mathematica or Sage notebook.
  • Tal Galili
    Tal Galili over 13 years
    mbq: textual output includes tables/data.frames/lm.summary and so on. It is true that outputting it as text (ascii) is fine. Although the better solution would be something like R2HTML, but without the need to add all those lines of code around every output statement.
  • chl
    chl over 13 years
    @Tal BTW, with ascii you not only get a readable plain text file but also an HTML page (asciidoc will format the txt file); less powerful than Sweave, but you work with just a text file, so...
  • Tal Galili
    Tal Galili over 13 years
    Hi chl, thanks - the ascii package does look nice. Though I still hope for a simpler solution for smaller snippets of code :)
  • mbq
    mbq over 13 years
    @chl Conversion is one thing, catching output (especially images) is something other. @Tal Again -- you'll not find it, print and plot cannot be hooked in any low-level enough way.
  • mbq
    mbq over 13 years
    @Jeromy with data uri scheme, see my answer.
  • chl
    chl over 13 years
    @mbq (+1) Yes, I agree. This is why I initially suggested to rely on an external scripting language to call R in batch mode; now, if we look for a simpler solution, I do not know how we can do that.
  • Tal Galili
    Tal Galili over 13 years
    Hi chl, I have seem to have found a solution doing what you are describing! Please have a look at the answer I just posted. Best, Tal
  • chl
    chl over 13 years
    Oh, I seem to remember browsing the webiste some time ago, but definitively forgot about it. It remind me of the technique used on bm2.genes.nig.ac.jp to display complete R output. Let us know if you can manage to only display the output (text+img) and not the R command...
  • Tal Galili
    Tal Galili over 13 years
    Hi chl, I already contacted the author of that plugin. I hope that this could be accomplished (and actually much more). More (I hope) to come...
  • Tal Galili
    Tal Galili over 13 years
    Hi chl, regarding the link you gave, I forget about it. Interestingly enough, it doesn't solve the issue, since he has all the ?sink output and then all the ?png output (I am not sure if that is how he implements it, but that's the result). This indeed could be a good idea for upgrading such a website.