knitr/Sweave 中的 If-Else 语句使用 R 变量作为条件

If-Else Statement in knitr/Sweave using R variable as conditional

我目前在 R 和 RStudio 中使用 knitr 来生成 LaTeX 输出。我的代码是一个 .Rnw 文件(称为 testKnitr.Rnw),它被编译为一个 pdf 文件:

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

我想在 LaTeX 中使用 if-else 语法,以便根据 R 变量的值,输出两个 LaTeX 文本段落之一。在这些 LaTeX 段落中,我想使用像 \Sexpr{} 和 \ref.

这样的表达式

我有一个基于此处发布的类似问题的第二个答案的最小工作示例:

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

这是 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}

理想情况下,上述 MWE 的预期输出将是一份包含一行内容的报告:

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

"This means x value of -0.87 was less than 0"

在回答这个问题之前,我想先看一下这个是否应该的元问题。

我们应该这样做吗?

我不这么认为。我们在这里基本上做的是使用 knitr 在文档中插入 \Sexpr{x} 然后解释 \Sexpr{x}。没有(明显的)理由说明为什么我们应该绕道而行,而不是将 x 的值直接插入到文档中。

怎么做?

下面的最小示例展示了如何完成它:

\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}

这里有两点很重要:

  • 我们需要转义 \Sexpr 中的反斜杠,结果是 \Sexpr.
  • 我们需要设置knit_patterns$set(header.begin = NULL).

编译文档:

  • 另存为doc.Rnw.
  • 然后执行:

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

会发生什么?

knit 的第一次调用生成具有以下内容的 intermediate.Rnw

\documentclass{article}

\begin{document}

Testing the code:

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

\end{document}

您应该注意到 knitr 没有像 LaTeX 代码一样包含任何定义、命令等。这是由于设置 header.begin = NULL 和记录 here。我们需要这种行为,因为我们想在第二步中再次 编织生成的文档,而当相同的东西被定义两次时,LaTeX 不喜欢它。

创建新环境 knitEnv 并将其设置为 envir 是可选的。如果我们跳过这个,变量 x 将在全局环境中创建。

第二步我们使用knit2pdf编织intermediate.Rnw然后立即生成PDF。如果第一步使用了envir,我们这里也需要使用它。这就是 x 及其价值从第一次编织到第二次编织步骤的传递方式。

这次包括了所有血淋淋的 LaTeX 内容,我们得到 doc_final.tex

\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}