创建一个空命令

创建一个空命令

在我的研究中,我用 R 进行分析,用 LaTeX 撰写论文。为了避免在分析发生变化时更新论文中的值,我直接从 R 更新论文中的值。

假设RI中有变量foo <- bar

现在,我在 LaTeX 中有一个占位符,其中有一组括号表示foo值,然后是一个标签,以便 R 可以找到正确的括号来放置值。

其中一个例子foo <- bar可能是:

Lorem ipsum dolor sit amet {}\label{R.foo}, consectetur adipiscing elit.

因此,R 会找到一个预定义标签(在本例中为R.foo),然后将第一个括号内的内容替换为foo的值(此处为bar)。因此,在 R 运行后,我们将得到:

Lorem ipsum dolor sit amet {bar}\label{R.foo}, consectetur adipiscing elit.

问题是,我们会得到多个定义的标签(因为\label{R.foo}R 处理完成后文件中仍留有多个位置),我的 LaTeX 编辑器会对此发出警告。因此,我尝试创建一个完全没有 LaTeX 功能的替代方案 — 它应该只是 R 可以搜索的东西。

答案1

我会让 R 创建一个values.tex包含内容的不同文件

\newcommand{\Rfoo}{bar}

然后你的主文件就会有

\input{values}
%\providecommand{\Rfoo}{} % avoid an error if \Rfoo wasn't defined
...
Lorem ipsum dolor sit amet \Rfoo, consectetur adipiscing elit.

答案2

方法 1:

正如 Fran 所建议的使用针织品。 有针织品从 .Rnw 文件或 .Rtex 文件为您创建 .tex 文件,其中 R 代码块和 TeX 代码合并,并且在创建 .tex 文件时,执行 R 代码块的结果将放入 .tex 文件中。(knitr 可与在线 TeX 平台配合使用背面如果要编译的文件没有扩展名“.tex”但有扩展名“.Rtex”。)

使用以下 knitr 示例(必须以文件扩展名“.Rtex”保存),R 代码块计算勾股数:

<<templates, include=FALSE, cache=FALSE, echo=FALSE, results='asis'>>=
knitr::opts_template$set(
  JustResult = list(include=TRUE, cache=FALSE, echo=FALSE, results='asis')
)
PrintTriple <- function(k, s, t) {
    return(cat(
      "With \\(k=", k, "\\) and \\(s=", s, "\\) and \\(t=", t, "\\) you get \\(a=", (k*2*s*t), "\\), \\(b=", (k*((s*s)-(t*t))),
      "\\) and \\(c=", (k*((s*s)+(t*t))), "\\) and \\mbox{\\(a^2+b^2=c^2\\leftrightarrow(",
      (k*2*s*t),")^2+(",(k*((s*s)-(t*t))),")^2=(",(k*((s*s)+(t*t))),")^2","\\)}."
      , sep="", fill=FALSE
    ))
}
@

\documentclass{article}
\usepackage{amsmath, amssymb}
\DeclareMathOperator{\ggd}{ggd}

\parindent=0ex
\parskip=\medskipamount

\begin{document}

Use the following recipe to calculate triples
\((a, b, c)\) where the condition \(((a^2+b^2=c^2)\land(\{a,b,c\}\subset\mathbb{N})\land((a\equiv0\pmod{2}))\) is fulfilled---such triples are called \textbf{Pythagorean triples}:

Choose natural numbers \(k,s,t\); \(s>t\) and set:

\begin{equation*}
\begin{aligned}
a &\longleftarrow k2st\\
b &\longleftarrow k(s^2-t^2)\\
c &\longleftarrow k(s^2+t^2)
\end{aligned}
\end{equation*}

(If and only if \((k=1)\land(\gcd(s,t) = 1)\land(s\not\equiv t \pmod{2})\), then \((a, b, c)\) is called a \textbf{primitive} Pythagorean triple.)

\noindent
<<, opts.label='JustResult' >>=
PrintTriple(2, 4, 3)
@

\noindent
<<, opts.label='JustResult' >>=
PrintTriple(2, 3, 1)
@

\noindent
<<, opts.label='JustResult' >>=
K=1
S=2
T=1
PrintTriple(K, S, T)
@

\noindent
<<, opts.label='JustResult' >>=
K=3*K
S=2
T=1
PrintTriple(K, S, T)
@

\noindent
<<, opts.label='JustResult' >>=
S=3*S
T=3*T
PrintTriple(K, S, T)
@

\end{document}

在此处输入图片描述


方法 2:

也许你的 R 程序可以编写一个ValuesCalculatedByR.tex包含以下内容的.tex 文件

cathetus1={3,3},
cathetus2={4,4},
hypotenuse={5,5},

即以逗号分隔的模式列表⟨标识符⟩={⟨计算值⟩}。

(花括号中的⟨计算值⟩s 可以省略,如果⟨计算值⟩s 本身不包含逗号,如果你不介意周围的空格⟨计算值⟩正在被移除。)

并且 .tex 文件可以从中创建一个 expl3 属性列表并定义一个命令,以便\command{<identificator>}产生 <calculated value>

% I don't have R available right now for creating the file, thus I let the filecontents*-
% environment do that for me:
\begin{filecontents*}{ValuesCalculatedByR.tex}
cathetus1={3,3},
cathetus2={4,4},
hypotenuse={5,5},
FirstTokenIsExpandable=\LaTeX\space is funny and the value is defined.,
\end{filecontents*}
% The <value> "\LaTeX\space is funny and the value is defined."
% of the <identificator> "FirstTokenIsExpandable" does not
% contain comma, thus surrounding curly braces can be omitted.

\ExplSyntaxOn
% -------------------------------------------------------------------------------------------------------
% \ImportIDValueList{<.tex-input-file containing list of pattern <identificator>={<calculated value>} >}
%                   {<command for retrieving <calculated value> associated to <identifictor> >}
% -------------------------------------------------------------------------------------------------------
\cs_new_protected:Npn \ImportIDValueList #1#2 {
  % #1 = name of .tex-input-file created by the program R
  % #2 = to-be-defined command for retrieving calculated value
  \exp_args:Nno \use:n 
                { \exp_args:Nno \use:n { \__Christian_ImportIDValueList:nn{#1} } } 
                { \cs_to_str:N #2 }
}
\cs_new:Nn \__Christian_ImportIDValueList:nn{
  % #1 = name of .tex-input-file created by the program R
  % #2 = name of to-be-defined command for retrieving calculated value
  \cs_new_protected:cpn { #2 } ##1 { 
    \exp:w \__Christian_ImportValue_GetValue:nnnn { #1 } { Christian_ImportValue_#2_prop } {##1} {
      \msg_error:nnnnn { Christian_ImportValue } { not-available } { #1 } { ##1 }
      \mbox{\textsf{?##1?}}
    } 
  }
  \cs_new:cpn { #2Expandable } ##1 ##2 { 
    \exp:w \__Christian_ImportValue_GetValue:nnnn { #1 } { Christian_ImportValue_#2_prop } {##1} { ##2 } 
  }
  \file_get:nnN {#1} {} {\l_tmpa_tl}
  \prop_gclear_new:c { Christian_ImportValue_#2_prop }
  % Can't use \prop_gset_from_keyval:Nn  because ~ needs to be before each <value> as 
  % - unlike unexpandable x-expansion of \prop_item:cn - expandable f-expansion of \prop_item:cn 
  % won't stop when \prop_item:cn has delivered the result and therefore
  % must be stopped by a ~ that gets gobbled by the f-expansion-
  % routine, which, I guess, is s.th. like "\romannumeral-`a"
  % so that expansion during parsing the <number>-quantity
  % continues until it is clear whether a to-be-discarded <optional
  % space> follows the tokens "-`a" denoting the negative number -97
  % while \romannumeral silently removes tokens denoting TeX-
  % <number>-quantities denoting non-positive values without
  % returning any tokens at all.
  \exp_args:NnV \use:n {
    \keyval_parse:nnn 
      { \__Christian_ImportValue_pass_iii_ii_to_i {\__Christian_ImportValue_propset:nnn { Christian_ImportValue_#2_prop }}{} }
      { \__Christian_ImportValue_propset:nnn { Christian_ImportValue_#2_prop } } 
  } { \l_tmpa_tl }
}
\cs_new:Nn \__Christian_ImportValue_pass_iii_ii_to_i:nnn { #1 {#3} {#2} }
\cs_new:Nn \__Christian_ImportValue_propset:nnn {
  \prop_gput:cnn {#1} {#2} {~#3}
}
\cs_new:Nn \__Christian_ImportValue_GetValue:nnnn {
  % #1 = name of .tex-input-file created by the program R
  % #2 = name of property list
  % #3 = value to be retrieved from of property list
  % #4 = tokens in case property is undefined
  \prop_if_in:cnTF { #2 } { #3 }
                   { \exp_args:Nnf \use:nn {\exp_end:} { \prop_item:cn { #2 }{ #3 } } }
                   { \exp_end: #4 }
}
\msg_new:nnnn { Christian_ImportValue } { not-available }
 { Value~for~identifier~"#2"~could~not~be~retrieved }
 { Seems~the~file~"#1"~does~not~have~"#2=...,"}
% -------------------------------------------------------------------------------------------------------
\ExplSyntaxOff

\documentclass{article}

\ImportIDValueList{ValuesCalculatedByR.tex}{\GetRValue}%
% The above 
% - makes a property-list of name "Christian_ImportValue_GetRValue_prop"
%   from the content of the file ValuesCalculatedByR.tex  and 
% - defines a command  \GetRValue{<property>} to check if <property> is defined
%   in the property-list "Christian_ImportValue_GetRValue_prop".
%   If so, the value of that property is delivered.
%   If not so, an error-message is raised and ?<name of property>? is delivered.
%   The command is not expandable but protected.
% - defines a command  \GetRValueExpandable{<property>}{<tokens if <property> is undefined>} 
%   to check if <property> is defined in the property-list "Christian_ImportValue_GetRValue_prop".
%   If so, the value of that property is delivered.
%   If not so, <tokens if <property> is not available> is delivered.
%   The command is expandable.
%   The result is delivered by triggering two expansion-steps.
%   This might be important in case you need to "lay hands" on the result for
%   further examination. E.g., you may wish to have LaTeX examine the value
%   and fork the way of typesetting the value depending on whether the value does 
%   or does not contain a decimal separator. Or whatever.

\begin{document}

\noindent Unexpandable commands:\medskip

\noindent Test 1)\medskip

\[ (\GetRValue{cathetus1})^2+(\GetRValue{cathetus2})^2=(\GetRValue{hypotenuse})^2 \]

%% This yields an error-message and ?undefined value?:
% \GetRValue{undefined value}

\medskip\hrule\medskip\hrule\medskip

\noindent Expandable commands:\medskip

\noindent Test a)\medskip

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\Mytempa
\expandafter\expandafter\expandafter{\GetRValueExpandable{cathetus1}{n/a}}%

\texttt{\string\Mytempa=\meaning\Mytempa}

\(\Mytempa\)

\medskip\hrule\medskip

\noindent Test b)\medskip

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\Mytempb
\expandafter\expandafter\expandafter{\GetRValueExpandable{cathetus2}{n/a}}

\texttt{\string\Mytempb=\meaning\Mytempb}

\(\Mytempb\)

\medskip\hrule\medskip

\noindent Test c)\medskip

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\Mytempc
\expandafter\expandafter\expandafter{\GetRValueExpandable{hypotenuse}{n/a}}

\texttt{\string\Mytempc=\meaning\Mytempc}

\(\Mytempc\)

\medskip\hrule\medskip

\[ (\Mytempa)^2+(\Mytempb)^2=(\Mytempc)^2 \]

\medskip\hrule\medskip

\noindent Test d)\medskip

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\Mytempd
\expandafter\expandafter\expandafter{\GetRValueExpandable
                                        {undefined value}%
                                        {\LaTeX\space is funny but the value
                                         ``undefined value'' is undefined.}%
                                    }

\texttt{\string\Mytempd=\meaning\Mytempd}

\Mytempd

\medskip\hrule\medskip

\noindent Test e)\medskip

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\Mytempe
\expandafter\expandafter\expandafter{\GetRValueExpandable{FirstTokenIsExpandable}{n/a}}

\texttt{\string\Mytempe=\meaning\Mytempe}

\Mytempe

\end{document}

在此处输入图片描述

这样,R 程序就不需要在包含文档的 .tex 文件中进行替换。
它只需要创建一个额外的文本文件,其中包含逗号分隔的⟨标识符⟩={⟨计算值⟩}-list 然后由 LaTeX 通过以下方式加载

\ImportIDValueList{⟨file⟩}%
                  {⟨to‑be‑defined macro for retrieving a
                   ⟨calculated value⟩ stored in ⟨file⟩
                   by specifying an ⟨identificator⟩
                   in the argument⟩}%


方法 3:

让你的 R 程序创建一个以逗号分隔值列表形式存储为 .csv 文件的数据库,其中包含“标识符”和“值”字段,并使用包数据工具用于导入该数据库并检索值:

% With older LaTeX-kernels you need to activate/uncomment the following line:
%\RequirePackage{filecontents}

% I don't have R available right now for creating the file, thus I let the filecontents*-
% environment do that for me:
\begin{filecontents*}{ValuesCalculatedByR.csv}
cathetus1,"3,3"
cathetus2,"4,4"
hypotenuse,"5,5"
\end{filecontents*}

\documentclass[a4paper]{article}

\usepackage{datatool}

\DTLloaddb[noheader,keys={identificator,value}]{ValuesCalculatedByR}{ValuesCalculatedByR.csv}

\newif\ifvaluenotfound
\newcommand\resultscratch{}%

\newcommand{\GetRValue}[1]{%
   \global\valuenotfoundtrue
   \DTLforeach*[\DTLiseq{\identificator}{#1}]%
               {ValuesCalculatedByR}%
               {\identificator=identificator,\value=value}%
               {\global\valuenotfoundfalse\global\let\resultscratch=\value}%
   \ifvaluenotfound
     % Some error or warning-message could be here but I am too lazy at the moment.
     \textsf{?#1?}%
   \else
     \resultscratch
   \fi
}%


    
\begin{document}

\[ (\GetRValue{cathetus1})^2+(\GetRValue{cathetus2})^2=(\GetRValue{hypotenuse})^2 \]

%\GetRValue{Undefined}

\end{document}

在此处输入图片描述

答案3

我不清楚你到底想做什么,但我认为这是一种不必要的混乱方法。考虑使用knitr插入\Sexpr{}小的 R 输出(如数字或向量)或 R 块(<<>>=@行之间的代码)以获得更复杂的代码(表格、图表等)。请注意,您可以随时更改 foo 的值, \Sexpr{foo}并将相应更新:

\documentclass{article}
\begin{document}
<<Rchunkcode,echo=FALSE>>=
foo <- "bar" 
@
Lorem ipsum dolor sit amet \Sexpr{foo}, consectetur adipiscing elit.
<<AnotherRchunkcode,echo=FALSE>>=
foo <- "baz" 
@
Lorem ipsum dolor sit amet \Sexpr{foo}, consectetur adipiscing elit.
\end{document}

答案4

当我写下这个问题时,我找到了一个简单的解决方案。在\begin{document}“如果我调用新函数”之前R添加\newcommand{\R}[1]{}

例子:

Lorem ipsum dolor sit amet {bar}\R{R.foo}, consectetur adipiscing elit.

相关内容