UP | HOME |

Ejecutar un fichero Rnw con la clase Tufte-book

Ejecutar un fichero Rnw con la clase Tufte-book

Ejecutar un fichero Rnw, que combina programación en LaTeX y en R, para que el formato salga bonito con la clase tufte-book no es inmediato.

ejemplornwmargin.png Ponemos un ejemplo de fichero Rnw. En primer lugar, definimos las cabeceras habituales, especialmente el marginfix para que las notas del margen no sobresalgan por arriba o por abajo.

% pp.Rnw
\documentclass[a4paper,nobib,notoc]{tufte-book}
\usepackage{marginfix} % para el marginnote, marginfigure, que no se salga de la página
\usepackage[utf8]{inputenc}     % Linux
\usepackage[spanish,es-tabla,es-nodecimaldot,es-noshorthands]{babel} % Spanish titles
% \usepackage{fouriernc}          % Type of font
\usepackage[T1]{fontenc}        % To deal with non ascii characters
\usepackage{graphicx}           % To include graphs. See epslatex.pdf
\DeclareGraphicsExtensions{.pdf,.png,.jpg,.mps}
\graphicspath{{graphics/}}
\usepackage{lipsum}

Ahora empieza la programación básica. Knitr crea un kframe que no permite notas (floats) al margen. Lo ideal sería redefinir desde cero este entorno, aunque con esta aproximación funciona bastante bien. Creamos un comando reservarespaciovertical para que la etiqueta y el bloque de código permanezcan en la misma página. En el comando rchunk reservamos suficiente espacio vertical, incluimos la etiqueta como nota del margen al mismo nivel que el bloque, y dependiendo de si es página par o impar, la ubicamos al lado del código.

%% Para impedir que la etiqueta quede en página distinta al chunk
%% reservamos espacio vertical
\newcommand{\reservarespaciovertical}[2][0pt]{\rule{#1}{#2}\vspace{-#2}\vspace{-\parskip}\par}
\makeatletter
\newcommand*{\rchunk}[1]{\par\small\reservarespaciovertical{5\baselineskip}%
\vspace{\baselineskip}\vspace{\parskip}%Ajustamos para que quede al mismo nivel
\marginpar{%
\hbox{}%
\@tufte@marginnote@font\@tufte@marginnote@justification\@tufte@margin@par\noindent
\@tufte@checkoddpage% Alineado a izquierda o derecha, dependiendo de la página
\ifthenelse{\boolean{@tufte@odd@page}}%
{\RaggedRight}%
{\RaggedLeft}%
\hlcom{\texttt{R.\thechapter.\detokenize{#1}}}}%
\vspace{-\baselineskip}\vspace{-\parskip}}
\makeatother



Dos son los fallos que presenta esta aproximación. El primero es que reserva como espacio vertical 5 líneas, independientemente de las líneas de código del bloque. El segundo fallo es que LaTeX ajusta los párrafos hacia arriba o hacia abajo dependiendo del texto que incluya en esa página. Al ajustar la ubicación vertical de los párrafos, la correspondiente etiqueta ya no queda al mismo nivel que el código. La forma de solucionarlo sería redefinir enteramente el entorno kframe.

Una cuestión que no he mirado con detalle es que el color de fuente de las notas al margen cambiaba al emplear knitr. Redefiní el marginnote para que la fuente sea de color negro.

%% El marginnote se vuelve tonto con los colores con el knitr. Hemos introducido el color{black}
\makeatletter
\renewcommand\marginnote[2][0pt]{%
\ifthenelse{\boolean{@tufte@loadnatbib}}{%
\let\cite\@tufte@infootnote@cite%   use the in-sidenote \cite command
}{}%
\gdef\@tufte@citations{}%           clear out any old citations
%\marginpar{\hbox{}\vspace*{#1}\@tufte@marginnote@font\@tufte@marginnote@justification\@tufte@margin@par\vspace*{-1\baselineskip}\noindent\color{black} #2}%
\marginpar{\hbox{}\vspace*{#1}\@tufte@marginnote@font\@tufte@marginnote@justification\@tufte@margin@par\noindent\color{black} #2}%
\@tufte@print@citations%            print any citations
\ifthenelse{\boolean{@tufte@loadnatbib}}{%
\let\cite\@tufte@normal@cite%       go back to using normal in-text \cite command
}{}%
}
\makeatother

Dentro del documento LaTeX introducimos un código de R para caracterizar el knitr. Lo más relevante es que empleo el estilo styler para formatear el código y las figuras se almacenan en un subdirectorio. El color de las fuentes de las notas al margen cambiaba y no sé porqué. En este caso como he tenido problemas con el color de las notas al margen, redefiní para que el color del pie de figura fuera negro.

Y lo más interesante es que introduje el comando rchunk de LaTeX con la etiqueta correspondiente.

%% =====================================================================
\begin{document}


<<nochunk00, eval = TRUE, echo = FALSE, results="hide", purl = FALSE>>=
## https://yihui.org/knitr/options/
knitr::opts_chunk$set(fig.width=7, # $
fig.height=7, fig.path='figure3a/', out.width='0.8\\linewidth',
tidy="styler", #"formatR",
tidy.opts=list(strict =TRUE))
##tidy="styler",tidy.opts=list(width.cutoff=60)
knitr::knit_hooks$set(colorcaption = function(before, options, envir) { # $
## Hacked from hook_plot_custom
if (before) return() # run hook after the chunk
ext = "pdf" #  original: options dolar fig.ext %n% dev2ext(options dolar dev)
hook = knitr::knit_hooks$get('plot')
##
n = options$fig.num # $
if (n == 0L) n = options$fig.num = 1L # $ make sure fig.num is at least 1
res = unlist(lapply(seq_len(n), function(i) {
options$fig.cur = i # $
hook(knitr::fig_path(ext, options, i), knitr:::reduce_plot_opts(options))
}), use.names = FALSE)
res <- paste(res, collapse = '') 
## My hack. Put the color after the end of kframe
sub("\\end{kframe}",paste0("\\end{kframe}\\color{",options$colorcaption, "}"),res,fixed=TRUE) # $
})
## Añadir un marginnote con el nombre del chunk
knitr::knit_hooks$set(chunk = function(x,options) { # $
label <- opts_current$get("label") # $
salida <- knitr:::hooks_latex()$chunk(x,options) # $
res <- sub("\\begin{knitrout}",paste0("\\begin{knitrout}\\rchunk{",label,"}\\small"),salida,fixed=TRUE)
res
})

options(width=60) # Ancho de los resultados

## ============================================================
## Código para genererar datos
## ============================================================
@

Para incluir una figura en el margen, creamos dos bloques de código, el primero no se evalúa y muestra el código de R del segundo bloque. El segundo bloque está dentro del marginfigure, no se presenta el código, y su salida es asis.



\lipsum[1]
<<chunk1,eval=FALSE,ref.label="nochunk100">>=
@

\begin{marginfigure}
    \centering
    <<nochunk100,echo=FALSE,results="asis",out.width="1\\linewidth">>=
    ## Simulación de Montecarlo
    x <- rgamma(1e5, 7, 2) # Muestra empírica
    hist(x,prob=TRUE,main="Aproximación de Montecarlo")
    curve(dgamma(x,7,2),add=TRUE) # Distribución teórica
    @
    \caption{El método de Montecarlo indica que la distribución empírica ajusta a la distribución teórica cuando el tamaño muestral es suficientemente grande.}
    \label{fig:montecarlo}
\end{marginfigure}

\lipsum[2]

\end{document}

Por último, el código que ejecuto en R para procesar todo esto extrae el código de R, crea el fichero tex y lo compila.

setwd('/home/emilio/temp/ejecutarrnw')
require(knitr);
knitr::knit('/home/emilio/temp/ejecutarrnw/pp.rnw',output='/home/emilio/temp/ejecutarrnw/pp-woven.R',tangle = TRUE); knitr::knit('/home/emilio/temp/ejecutarrnw/pp.rnw', output='/home/emilio/temp/ejecutarrnw/pp-woven.tex');
system('latexmk -pdf -shell-escape /home/emilio/temp/ejecutarrnw/pp-woven.tex')