r - knit/Sweave 中使用 R 变量作为条件的 If-Else 语句(第 2 部分)

标签 r if-statement latex knitr sweave

我正在扩展我在这里发布的问题:

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

我想在 LaTeX 中使用 if-else 语法,以便根据 R 变量(例如 x)的值,输出两个 LaTeX 文本段落之一。如果 x>0,则 LaTeX 段落有一个图形和一个表格。但是,如果 x<0,则 LaTeX 段落只有一个图形(没有表格)。

我有一个可以工作的 MWE,它基于上一篇文章中检查过的答案:

\documentclass[12pt,english,nohyper]{tufte-handout}
\usepackage{tabularx}
\usepackage{longtable}

\begin{document}

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

<<echo=FALSE,results='asis'>>=
fname="myOutput.pdf"
pdf(fname,width=4,height=4)
print(qplot(mpg,cyl,data=mtcars))
{dev.off();invisible()}
cat(sprintf('\\begin{marginfigure}
\\includegraphics[width=0.98\\linewidth]{%s}
\\caption{\\label{mar:dataMtcars}Comments about mtcar dataset.}
\\end{marginfigure}',sub('\\.pdf','',fname)))
@

<<echo=FALSE,results='asis'>>=
x<- rnorm(1)
if (x>0){
  myDF = data.frame(a=rnorm(1:5),b=rnorm(1:5),c=rnorm(1:5))
  print(xtable(myDF,caption='Data frame comments', label='tab:myDataFrame'),floating=FALSE, tabular.environment = "longtable",include.rownames=FALSE)
}
@

<<condition, echo=FALSE>>=
if(x>0){
  text <- "Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of \\Sexpr{x} was greater than 0. Table \\ref{tab:myDataFrame} shows my data frame."
  }else{
  text <- "Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of \\Sexpr{x} was less than 0. We do not show a data frame."
  }
@

Testing the code: 

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

\end{document}

然后我将此 MWE 保存为 testKnit.Rnw 之类的文件,然后运行:

knit(input = "testKnitr.Rnw", output = "intermediate.Rnw")
knit2pdf(input = "intermediate.Rnw", output = "doc_final.tex")

我想知道我是否有效地创建了这段代码,特别是因为我在上一篇文章中向我指出 - 在仅使用\Sexpr{} 的情况下 - 有更简单的解决方案。这里要织两遍有点麻烦。

有没有一种更简单的方法来合并我的 if/else 语句来显示包含变量值、数字和/或表格的两个段落之一,所有这些都基于变量的值?谢谢。

最佳答案

类似于related question that has been linked above在这种情况下,不需要动态生成 \Sexpr{} 并再次解析中间输出。

问题的代码中发生了很多事情,但这是关键 block (其中 x 获取在前一个 block 中分配的随机值):

<<condition, echo=FALSE>>=
if (x > 0) {
  text <- "Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of \\Sexpr{x} was greater than 0. Table \\ref{tab:myDataFrame} shows my data frame."
  } else {
    text <- "Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of \\Sexpr{x} was less than 0. We do not show a data frame."
    }
@

直接替代打印\Sexpr

\Sexpr{} 的直接替代方案是 pastesprintf (我在 if 分支中使用一个以及 else 分支中的一个仅用于演示):

<<condition, echo=FALSE>>=
if (x > 0) {
  text <- paste("Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of", x, "was greater than 0. Table \\ref{tab:myDataFrame} shows my data frame.")
  } else {
    text <- sprintf("Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of %f was less than 0. We do not show a data frame.", x)
    }
@

当要有条件显示的文本不太长时,此方法效果很好。否则,使用 LaTeX if 语句可能会更方便。这样做的优点是字符字符串/代码块中不会包含太多代码。然后,\Sexpr{} 可能会再次有用。

使用 LaTeX 条件表达式

many ways to write conditional expressions in LaTeX ,但最简单的形式就足够了。

  • 首先,定义一个新的 if,我们将其命名为 ifPositive: \newif\ifPositive
  • 其次,使用 R 插入 \Positivetrue\Positivefalse 到文档中。
  • 第三,使用\ifPositive …\else …\fi

    \newif\ifPositive
    
    <<condtion2, echo = FALSE, results = "asis">>=
    if (x > 0) {
      cat("\\Positivetrue")
    } else {
      cat("\\Positivefalse")
    }
    @
    
    \ifPositive
    Figure \ref{mar:dataMtcars} shows the mtcars data set. The x value of \Sexpr{x} was greater than 0. Table \ref{tab:myDataFrame} shows my data frame.
    \else
    Figure \ref{mar:dataMtcars} shows the mtcars data set. The x value of \Sexpr{x} was less than 0. We do not show a data frame.
    \fi
    

其他备注

在问题中,有一个 block 会生成myOutput.pdf。其中使用了 pdf()dev.off()。这不是一个好的风格,kills kittens 。无需绕过 knitr 的绘图机制;即使使用像 marginfigure 而不是 figure 这样的自定义环境也是如此。该 block 应该替换为如下内容:

<<dataMtcars, echo=FALSE, fig.env = "marginfigure", out.width = "0.98\\linewidth", fig.cap = "Comments about mtcar dataset.", fig.lp = "mar:">>=
print(qplot(mpg,cyl,data=mtcars))
@

fig.lp = "mar:" 仅在生成与问题 mar:dataMtcars 中完全相同的标签时才需要。如果标签 fig:dataMtcars 也可以的话,可以跳过它。

文档

最后,这里是完整的文档:

\documentclass[12pt,english,nohyper]{tufte-handout}
\usepackage{tabularx}
\usepackage{longtable}

\begin{document}

<<setup, echo = FALSE>>=
library(knitr)
library(xtable)
library(ggplot2)
@

<<dataMtcars, echo=FALSE, fig.env = "marginfigure", out.width = "0.98\\linewidth", fig.cap = "Comments about mtcar dataset.", fig.lp = "mar:">>=
print(qplot(mpg,cyl,data=mtcars))
@

<<echo=FALSE,results='asis'>>=
x <- rnorm(1)
if (x > 0) {
  myDF <- data.frame(a = rnorm(1:5), b = rnorm(1:5), c = rnorm(1:5))
  print(xtable(myDF, caption= 'Data frame comments', label='tab:myDataFrame'), floating = FALSE, tabular.environment = "longtable", include.rownames=FALSE)
}
@

<<condition, echo=FALSE>>=
if (x > 0) {
  text <- paste("Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of", x, "was greater than 0. Table \\ref{tab:myDataFrame} shows my data frame.")
  } else {
    text <- sprintf("Figure \\ref{mar:dataMtcars} shows the mtcars data set. The x value of %f was less than 0. We do not show a data frame.", x)
    }
@

  Testing the code:

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

\paragraph{Alternative:}

\newif\ifPositive

<<condtion2, echo = FALSE, results = "asis">>=
if (x > 0) {
  cat("\\Positivetrue")
} else {
  cat("\\Positivefalse")
}
@

\ifPositive
Figure \ref{mar:dataMtcars} shows the mtcars data set. The x value of \Sexpr{x} was greater than 0. Table \ref{tab:myDataFrame} shows my data frame.
\else
Figure \ref{mar:dataMtcars} shows the mtcars data set. The x value of \Sexpr{x} was less than 0. We do not show a data frame.
\fi

\end{document}

关于r - knit/Sweave 中使用 R 变量作为条件的 If-Else 语句(第 2 部分),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32505959/

相关文章:

r - 在 R 中更改数据帧结构

r - 如何将时间戳转换为字符串(不更改时区)?

java - Java猜数程序问题

latex - (La)TeX Base 10 定点运算

r - 如何在 LPSolve 中实现完全不同的约束?

r - 向 ggplot2 散点图添加文本标签

r - dplyr ifelse 语句中的嵌套条件

Javascript > 运算符在扩展中不起作用

python - 如何在 ipython-notebook 中获取 sympy 表达式的 latex 表?

c# - 找不到初始化文件 gs_init.ps