4

I am currently using knitr in R and RStudio to produce a LaTeX output. My code is a .Rnw file (called, say, testKnitr.Rnw) that is compiled to a pdf file with:

knit("testKnitr.Rnw") // in RStudio
pdflatex testKnitr.tex // in terminal

I would like to use an if-else syntax in LaTeX so that, depending on the value of an R variable, one of two LaTeX text paragraphs are output. In these LaTeX paragraphs, I would like to use expressions like \Sexpr{} and and \ref.

I have a minimal-working-example that is based on the second answer to a similar question posted here:

How to write an if-then statement in LaTeX using the value of an R variable in knitr/Sweave

Here is the MWE:

\documentclass{article}

\begin{document}

<<include=FALSE>>=
library(knitr)
opts_chunk$set(
concordance=TRUE
)
@

<<condition, include=FALSE, echo=FALSE>>=
x<- rnorm(1)
if(x>0){
  text <- "This means x value of \Sexpr{x} was greater than 0"
  }else{
  text <- "This means x value of \Sexpr{x} was less than 0"
  }
@

Testing the code: 

<<print, results='asis', echo=FALSE>>=
cat(text)
@

\end{document}

Ideally, the intended output of the above MWE would a report with one line that contained something like:

"This means x value of 0.87 was greater than 0"

or

"This means x value of -0.87 was less than 0"
Community
  • 1
  • 1
  • 2
    You could include the value in the output with `text <- paste("This means x value of", x, "was greater than 0")`. Would that not work in your non-minimal case? – David Robinson Sep 10 '15 at 04:00
  • 1
    Thank you @DavidRobinson. I might have to create a better MWE! Because, I am trying to get LaTeX syntax like \Sexpr{} and \ref{} into the text. So, I don't think your solution could work for something like \ref{}. –  Sep 10 '15 at 05:43

1 Answers1

4

Before answering this question, I would like to take a look at the meta-question of whether this should be done.

Should we do it?

I don't think so. What we are basically doing here is using knitr to insert \Sexpr{x} in a document and then interpret \Sexpr{x}. There are no (obvious) reasons why we should take this detour instead of inserting the value of x directly to the document.

How to do it?

The following minimal example shows how it could be done anyways:

\documentclass{article}

\begin{document}

<<setup, echo = FALSE>>=
library(knitr)
knit_patterns$set(header.begin = NULL)
@

<<condition, echo=FALSE>>=
x <- rnorm(1)
if (x > 0) {
  text <- "This means x value of \\Sexpr{x} was greater than 0"
  } else {
    text <- "This means x value of \\Sexpr{x} was less than 0"
  }
@

Testing the code:

<<print, results='asis', echo=FALSE>>=
cat(text)
@

\end{document}

Two things are important here:

  • We need to escape the backslash in \Sexpr, resulting in \Sexpr.
  • We need to set knit_patterns$set(header.begin = NULL).

To compile the document:

  • Save it as doc.Rnw.
  • Then execute:

    knitEnv <- new.env()
    knit(input = "doc.Rnw", output = "intermediate.Rnw", envir = knitEnv)
    knit2pdf(input = "intermediate.Rnw", output = "doc_final.tex", envir = knitEnv)
    

What happens?

The first call of knit generates intermediate.Rnw with the following content:

\documentclass{article}

\begin{document}

Testing the code:

This means x value of \Sexpr{x} was less than 0

\end{document}

You should note that knitr didn't include any definitions, commands etc. as usual to the LaTeX code. This is due to setting header.begin = NULL and documented here. We need this behavior because we want to knit the resulting document again in the second step and LaTeX doesn't like it when the same stuff is defined twice.

Creating the new environment knitEnv and setting it as envir is optional. If we skip this, the variable x will be created in the global environment.

In the second step we use knit2pdf to knit intermediate.Rnw and immediately generate a PDF afterwards. If envir was used in the first step, we need to use it here too. This is how x and it's value are conveyed from the first to the second knitting step.

This time all the gory LaTeX stuff is included and we get doc_final.tex with:

\documentclass{article}\usepackage[]{graphicx}\usepackage[]{color}
%% maxwidth is the original width if it is less than linewidth
%% otherwise use linewidth (to make sure the graphics do not exceed the margin)
\makeatletter
\def\maxwidth{ %
  \ifdim\Gin@nat@width>\linewidth
    \linewidth
  \else
    \Gin@nat@width
  \fi
}
\makeatother

%% more gory stuff %%


\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\begin{document}

Testing the code:

This means x value of \ensuremath{-0.294859} was less than 0

\end{document}
CL.
  • 14,577
  • 5
  • 46
  • 73
  • Thank you @user2706569 for your detailed post! Sometimes, when I create MWE, in an attempt to remove superfluous information, I inadvertently remove important information. In this case, I believe I removed the information on *why* we should do it. Really, I am also doing things not just \Sexpr{}, but also with \ref{}. That is why (I believe) I cannot just print the value of the variable in \Sexpr{}, because it would not solve \ref{}. –  Sep 10 '15 at 15:19
  • 2
    I don't think that \Sexpr and \ref are comparable. \ref is a LaTeX command and is resolved during compilation (TEX --> PDF). – CL. Sep 10 '15 at 15:24
  • Thank you, @user2706569. I have been very poor at figuring out when certain syntax are compiled, but I appreciate your explanation. I posted a similar question here (http://stackoverflow.com/questions/32505959/if-else-statement-in-knitr-sweave-using-r-variable-as-conditional-part-2) in case anyone is interested. I have MWE using both \Sexpr and \ref there, that hopefully does not over-simplify what I am trying to do the most efficient way. Thanks again. –  Sep 10 '15 at 15:29
  • Regarding the syntax: Usually everything with `\command{}` is LaTeX. `\Sexpr` is a nasty exception. I'll have a look at the other question later. – CL. Sep 10 '15 at 15:34
  • Thank you. I had thought \command{} was usually LaTeX, and was pretty confused to learn that \Sexpr is not. Relieved to know it is an exception! –  Sep 10 '15 at 15:47