Sweave
Sweave es una función de R que se inscribe en lo que se ha venido a denominar Literate Statistics. El objetivo es tener entremezclado en un único fichero de sintaxis tanto el texto (en formato LaTeX o HTML) y el código estadístico de R. Cuando se procesa el código, el output mezcla automáticamente el texto con las tablas y otros objetos de R, lo que facilita enormemente algunas tareas como la generación periódica de informes o de textos cuando se cambian, aunque sea mínimamente, los datos de origen.
Si quieres, puedes consultar también nuestra guía sobre como poner en funcionamiento un completo sistema de trabajo para la investigación en medicina.
Requerimientos
- Tener instalado y funcionando el sistema R.
- Una distribución LaTeX instalada y funcionando (teTex con texinfo y tetex-extra en GNU/Linux o MiKTeX en M$). Lógicamente no es necesario si se desea la integración en HTML y no en LaTeX.
- Un editor de sintaxis, preferentemente Emacs con auctex y noweb, aunque bajo M$ se puede usar también WinEdt o Tinn-r que és lliure que et coloreja la sintaxi de R, LaTeX i Sweave.
- Si se trabaja en Emacs, es aconsejable tener instalado el módulo Noweb que permite el coloreado de la sintaxis de Sweave (chunks), e identifica si se trata de un fragmento de texto o de código de R. Ningún otro editor permite esta función.
Sintaxis básica
Los archivos de sintaxis de Sweave deben guardarse con la extensión .Rnw.
La mayor parte del fichero tendrá la apariencia de un archivo de LaTeX o de un archivo HTML (incluidos todos los encabezados, etc.), aunque con la particularidad de contener chunks (Inglés: Trozo), que pueden entenderse como partes diferenciadas de la sintaxis correspondientes a distintos tipos de código.
Los chunks de texto, que corresponden a código de LaTeX o de HTML, deben ir precedidos por el signo @:
@ Aquí empieza el código de LaTeX o de HTML
Los chunks de código estadístico, que seran evaluados por R, deben ir precedidos por la cadena <<>>=:
<<>>= Código de R
El identificador de código de R puede contener o no argumentos. Caso de especificarse argumentos, la sintaxis tendrá el siguiente aspecto:
<<Argumento1=ValorDelArgumento1, Argumento2=ValorDelArgumento2, ...>>= Código de R
Si no se especifica ningun argumento se usarán los valores por defecto que hacen que en el documento final se muestre tanto el input (órdenes de R), como el output (resultados de R).
Estos argumentos funcionan a manera de interruptores para:
- Mostrar o no las órdenes de R: echo=TRUE o echo=FALSE
- Mostrar o no los resultados de R: results=show o results=hide
Otros posibles argumentos para estos chunks son:
- <<fig=TRUE, width=, height=>>= : Para indicar que el código que sigue a continuación generá como output un gráfico, con un ancho (width=) y altura (height=)
- results=tex : Para indicar que el código de R generará como resultado (output) directo un código de Latex, habitualmente mediante el uso de funciones de la librería xtable
- eval=FALSE : Para que el código no se evalúe en ese momento sino cuando se vuelva a llamar a ese chunk mediante su nombre, que se asigna con el argumento label=
- label= : Argumento optativo que asigna un nombre a ese chunk para poder referirnos a él posteriormente. Si el argumento label se especifica en primer lugar, no es necesario escribir la palabra label. En caso contrario debe escribirse:
<<resul2>>= o bien <<otroargumento=valorotroargumento,label=resul2>>=
Para referirnos posteriormente a ese chunk, usaremos el código:
<<argumentosdelnuevochunk>>= <<resul2>>
Es decir, crearemos un nuevo chunk con sus propios argumentos, y luego llamaremos al otro chunk mediante su label.
El ejemplo 5 ilustra el uso del argumento label.
Todos los argumentos que hemos revisado pueden establecerse por defecto con el código:
\SweaveOpts{argumentos}
los argumentos de código R establecidos mediante \SweaveOpts tendrán validez hasta que se especifique lo contrario, ya sea en un chunk concreto o estableciendo por defecto otros argumentos con un nuevo \SweaveOpts.
Por ejemplo, si queremos que por defecto no se muestren las órdenes de R (input):
\SweaveOpts{echo=false}
Hay que remarcar que los chunks de código se evalúan en el orden en el que aparecen. Si por ejemplo en un primer chunk tenemos el siguiente código:
<<echo=FALSE>>= x<-c(1,1,1,2,2,2,1,2) @
Posteriormente podremos usar en otro chunk:
<<echo=FALSE>>= x*3 @
Aunque, como ya se ha dicho, la forma natural de insertar código de R es mediante el uso de chunks de código, si se trata de una única expresión el código puede ir dentro de un chunk de texto con el uso de Expresiónes de Lenguage S: \Sexpr{}. que se rellenan con ordenes de R, asi:
@ En el estudio se incluyeron \Sexpr{length(seq(1,115))} sujetos.
Esta forma de introducir código sin chunks específicos es exclusiva de la integración con LaTeX y no funciona con código HTML.
Por otro lado, hay que tener en cuenta que si el primer chunk de texto está immediatamente después de los encabezados (es decir si no hay ningún chunk de código previamente), no es necesario especificar su inicio. En cambio, si el último chunk es de código de R, hay que especificar el inicio de un chunk de texto antes de los cierres del documento de LaTeX o de HTML.
Las reglas basicas se resumen en:
- Los identificadores de cada tipo de chunk son: <<argumentos=>>= para código R y @ para código LaTeX o HTML.
- Para incluir órdenes de R en un chunk de texto se utiliza \Sexpr{} (sólo para LaTeX)
Algunos ejemplos
- Ejemplo 1:
\documentclass[12pt]{report} \begin{document} Se incluyeron \Sexpr{length(x<-c(rep(c(1,2),225),rep(1,114)))} sujetos, con una proporcion de hombres del \Sexpr{100*round(prop.table(table(x))[1],2)} \%. <<echo=FALSE>>= x <- cbind(c(2,7),c(3,4)) @ La siguiente tabla muestra la distribucion de: <<results=tex,echo=FALSE>>= library(xtable) xtable(x) @ \end{document}
- Ejemplo 2:
<html> <<echo=FALSE>>= x <- cbind(c(2,7),c(3,4)) @ La siguiente tabla muestra la distribucion de: <<echo=FALSE>>= x @ </html>
- Ejemplo 3:
\documentclass[a4paper]{article} \SweaveOpts{echo=true} \begin{document} First we define a figure hook: <<results=hide>>= options(SweaveHooks = list(fig = function() par(mfrow=c(2,2)))) @ Then we setup variable definitions without actually evaluating them <<xydef,eval=false>>= x <- 1:10 y <- rnorm(x) @ Then we put the pieces together: \begin{center} <<fig=T>>= <<xydef>> lm1 <- lm(y~x) summary(lm1) plot(lm1) @ \end{center} \end{document}
- Ejemplo 4 (resultado aquí):
\documentclass[a4paper]{article} \begin{document} <<echo=false,results=hide>>= library(lattice) library(xtable) data(cats, package="MASS") @ \section*{The Cats Data} Consider the \texttt{cats} regression example from Venables \& Ripley (1997). The data frame contains measurements of heart and body weight of \Sexpr{nrow(cats)} cats (\Sexpr{sum(cats$Sex=="F")} female, \Sexpr{sum(cats$Sex=="M")} male). A linear regression model of heart weight by sex and gender can be fitted in R using the command <<>>= lm1 = lm(Hwt~Bwt*Sex, data=cats) lm1 @ Tests for significance of the coefficients are shown in Table~\ref{tab:coef}, a scatter plot including the regression lines is shown in Figure~\ref{fig:cats}. \SweaveOpts{echo=false} <<results=tex>>= xtable(lm1, caption="Linear regression model for cats data.", label="tab:coef") @ \begin{figure} \centering <<fig=TRUE,width=12,height=6>>= lset(col.whitebg()) print(xyplot(Hwt~Bwt|Sex, data=cats, type=c("p", "r"))) @ \caption{The cats data from package MASS.} \label{fig:cats} \end{figure} \begin{center} \end{center} \end{document}
- Ejemplo 5:
\documentclass[a4paper]{article} \begin{document} Primero ponemos el input: <<resultado,echo=TRUE,results=hide>>= 2+2 @ Y luego el output: <<resultado2,echo=FALSE>>= <<resultado>> @ \end{document}
Procesamiento
El procesamiento (compilado) de un archivo de Sweave se compone de un único paso si se trabajo con código HTML, y de dos pasos si se trabaja con código LaTeX.
Paso 1
Ejecutar la función Sweave() de R, que evaluará los chunks con código de R y convertirá el archivo .Rnw a un archivo .tex o .html según el driver que se use. Estos ficheros se generarán en el working directory, que se puede descubrir con la función:
getwd()
y cambiar con:
setwd("rutacompletadelnuevodirectorio")
Para realizar este primer paso hay que mandar una instrucción con la función Sweave a R, ya sea desde el propio programa o desde Emacs o WinEdt].
Si estamos trabajando con código LaTeX debemos teclear:
Sweave("c:/rutacompleta/nombredelarchivo.Rnw")
Con el código anterior obtendremos un fichero .tex que deberá ser compilado como se explica en el segundo paso.
Sin embargo, si no estamos trabajando en LaTeX sino en HTML, deberemos primero obtener el paquete R2HTML (tipo 3) y luego:
library(R2HTML) Sweave("c:/rutacompleta/nombredelarchivo.Rnw",driver=RweaveHTML)
Con el código anterior obtenemos directamente un fichero .html ya completo y visualizable con cualquier navegador.
En ambos casos, si no se especifica la ruta completa sinó sólo el nombre del archivo .Rnw, R lo buscará en el working directory actual.
Paso 2
Si estamos trabajando con código LaTeX hay que realizar un segundo paso, que consiste en compilar el documento .tex resultante del paso anterior para obtener, como es habitual en LaTeX, archivos .dvi, .ps o .pdf.
En sistemas M$ hay que realizar los dos pasos de forma independiente, ya sea con Emacs o con WinEdt.
En sistemas GNU/Linux, aunque también es posible realizar los pasos por separado, ambas tareas pueden automatizarse con el sistema que se explica a continuación.
Automatización del proceso con Emacs bajo GNU/Linux
Lo siguiente es sólo necesario si trabajamos con código LaTeX, pues la integración con HTML se realiza en un solo paso como se ha explicado anteriormente.
Antes de poder procesar automáticamente documentos de Sweave con código LaTeX hay que realizar el siguiente procedimiento, que deberá llevarse a cabo sólo una vez en cada ordenador y que permitirá ejecutar la función Sweave() de R sin necesidad de ejecutar manualmente el programa:
- Descargar este shell script, copiarlo a la ubicación /usr/local/bin/ y desde una ventana de terminal ejecutar:
sudo chmod +x /usr/local/bin/Sweave.sh
Una vez hecho esto, ya estamos en disposición de compilar documentos Sweave con código LaTeX en un solo paso. Para ello, debemos descargar este archivo Makefile (haciendo click con el botón derecho y pulsando Guardar enlace como) y editarlo para sustituir la expresión:
nombrearchivo
presente en las dos primeras líneas, por el nombre de nuestro fichero Sweave sin la extensión .Rnw.
El fichero Makefile debe situarse en el mismo directorio donde tengamos el archivo .Rnw.
Así, para cada proyecto Sweave que tengamos, deberemos tener un directorio independiente con dos archivos: fichero.Rnw y un Makefile que en las dos primeras líneas contenga el nombre del archivo .Rnw (sin la extensión).
Una vez hecho esto, debemos editar el archivo .Rnw en Emacs, grabarlo y pulsar:
M-x compile {Ret} make -k {Ret}
Este procedimiento va a generar dos archivos con el documento final, un .pdf y otro .ps. El fichero Makefile descargado es fácilmente costumizable para que cree sólamente uno de los dos ficheros resultado.
Se aconseja visualizar ambos tipos de archivos con el programa Gnome Ghost Viewer (es el visualizador por defecto de ficheros .ps), que actualiza directamente la vista de los archivos cuando estos cambian (es decir cada vez que se produce una nueva compilación) sin necesidad de tener que cerrar y volver a abrir el programa. Para que esto suceda, hay que marcar la opción Mira un fitxer en las preferencias del programa.
Todo lo anterior tiene la ventaja de permitir compilar archivos Sweave con una sola orden, lo que facilita la realización de compilaciones sucesivas para ir comprobando cómo está quedando nuestro documento, y detectar de forma temprana los errores en el código de R.
La compilación realizada con el procedimiento descrito tiene además otras ventajas, como por ejemplo que compila tantas veces como sea necesario el archivo .tex hasta que esté completo, lo que evita tener que recompilar manualmente los archivos que contienen, por ejemplo, referencias bibliográficas tal y como se explica en el artículo correspondiente.
La función Stangle
Permite extraer todo el código de R de un archivo Sweave (ya sea mezclado con LaTeX o con HTML) y guardarlo todo en un archivo .R, que contendrá sólamente código de R. De nuevo, este archivo se guardará en el working directory actual. La sintaxis de la función es la siguiente:
Stangle("nombrearchivo.Rnw")