动态格式化在 R/knitr/xtable 中生成的 LaTeX 表的标签/列

动态格式化在 R/knitr/xtable 中生成的 LaTeX 表的标签/列

我有一些来自统计包 R 的表格,我想以 LaTeX 标记的形式导出。

我想做每列与其标签的最长单词一样大(为简单起见,假设相关的表格值较短)。

如果标签如下:

Short label
Very long description
Three letter label

那么期望的输出(包括一些示例值)是:

Short   Very   long     Three
label   description     letter
                        label
-----------------------------
1       5               9
2       6               10
3       7               11
4       8               12
-----------------------------

人们可以在 R 中对表格标签/值进行各种各样的操作,但在 LaTeX 之外,R 本身只能计算表格标签的字符数,而不知道 LaTeX 引擎排版时所使用的实际空间。

大意

主要思想是从 R 脚本生成能够措施单词并使用 LaTeX 中计算的长度来设置实际的表格环境。LaTeX 测量文档的草稿如下:

...
\usepackage{varwidth, calc}     
...

\newlength{\temp}
%% Column 1     
\setlength{\temp}{\widthof{\fbox{\begin{varwidth}{\textwidth}
Short\\ label
\end{varwidth}}}}
\the\temp

%% Column 2
\setlength{\temp}{\widthof{\fbox{\begin{varwidth}{\textwidth}
Very \\ long \\ description
\end{varwidth}}}}
\the\temp

%% Column 3
\setlength{\temp}{\widthof{\fbox{\begin{varwidth}{\textwidth}
Three \\ letter \\ label
\end{varwidth}}}}
\the\temp

对其进行 Latex 处理后,我得到了以下输出:

30.71672pt
54.6612pt
32.38335pt

现在我可以在 R 中解析此输出并生成以下 LaTeX 代码:

\usepackage{array}
...
\def\tabcol{p{30.71672pt}p{54.6612pt}p{32.38335pt}}
\expandafter\tabular\expandafter{\tabcol}
\hline
Short label & Very long description & Three letter label \\\hline
1 & 2 &  3
\endtabular

期望的解决方案

我想知道我是否可以减少这个步骤并直接在 LaTeX 中执行,而不是解析 R 中第一个代码片段的输出,也就是说:我可以捕获长度 \temp 并将它们存储在某种“字符串变量”中,以便我可以在宏中使用它\tabcol

编辑

很多评论都在问我为什么不使用 knitr/Sweave 之类的东西。我没有详述这些细节,以免被标记为偏离主题。现在我想读者需要更多的见解。

首先我使用 Rnw+ knitr+ xtable。R-NoWeb 文档是 LaTeX 文档,其中穿插着特殊标记块(称为“代码块”):

<<...>>
 ... 
@

其中的点代表 R 代码或选项。knitr执行代码块中的 R 代码并将其替换为生成的 LaTeX 格式的输出(如果代码生成图形,knitr 将自动放置\includegraphics...指向图形文件的 ,除非您选择手动控制 LaTeX 输出)。由于 knitr 解析的文件是“普通”LaTeX 文件,因此您可以对其进行 latex 处理,这样您的报告就完成了。

至于表格,该模块xtable可以使用几个很酷的 LaTeX 环境( 等)将 R 数据对象转换为 LaTeX booktabstabularx据我所知,没有人可以像我尝试的那样自动调整表格大小。 tabularx可以做到,但使用不同的算法。

无论如何,在 R 中,很容易按列排列表格数据,并为每列生成类似于以下内容的 LaTeX 输出:

%% Column 1
\setlength{\temp}{\widthof{\fbox{\begin{varwidth}{\textwidth}
Short\\ label
\end{varwidth}}}}
\the\temp

如上所述,通过编译这些行(对每一列重复),我得到了所需的大小。为了捕获temp长度,我可能会使用:

\immediate\openout\tempfile=lengths.tex
\immediate\write\tempfile{\the\temp}
\immediate\closeout\tempfile

因此,实际的 R 生成的文件table.tex应该类似于:

\usepackage{varwidth, calc}
\usepackage{array}
 ...
\newlength{\temp}
\immediate\openout\tempfile=lengths.tex     
...

%% Column 1
\setlength{\temp}{\widthof{\fbox{\begin{varwidth}{\textwidth}
Short\\ label
\end{varwidth}}}}
%\the\temp
\immediate\write\tempfile{\the\temp}

%% Column 2
...

%% Column n
...

\immediate\closeout\tempfile
...

在 LaTeX 中编译后table.texlengths.tex生成。lengths.tex 可以在 R 中重新解析以读取其中的列值。table.tex可以生成一个新的

\usepackage{array}
 ...

\def\tabcol{p{...pt}p{...pt}...}
\expand\tabular\expandafter{\tabcol}

\endtabular

p{...pt}是从 获得的lengths.tex

可以将新的table.tex关联起来以获得最终结果,但是,如上所述,我想直接在 LaTeX 中自动解析第一个table.tex(或第一遍输出lengths.tex)(而无需在 R 和 LaTeX 之间来回切换)。

答案1

我认为我找到了一个可以接受的解决方案。

假设统计表示意图如下:

  Short label Very long description Three letter label
1           1                     5                  9
2           2                     6                 10
3           3                     7                 11
4           4                     8                 12

生成的 LaTeX 代码使每一列的大小与其标签的最长单词一样大是:

\documentclass{article}
\usepackage{varwidth, calc}
\begin{document}

%% LaTeX vars
\def\colDef{} 
\newlength{\temp}

%% Column 1 
\setlength{\temp}{\widthof{\mbox{\begin{varwidth}{\textwidth}
Short\\label
\end{varwidth}}}}
\edef\colDef{\colDef p{\the\temp}}

%% Column 2 
\setlength{\temp}{\widthof{\mbox{\begin{varwidth}{\textwidth}
Very\\long\\description
\end{varwidth}}}}
\edef\colDef{\colDef p{\the\temp}}

%% Column 3 
\setlength{\temp}{\widthof{\mbox{\begin{varwidth}{\textwidth}
Three\\letter\\label
\end{varwidth}}}}
\edef\colDef{\colDef p{\the\temp}}

\edef\colDef{{\colDef}}

%% Table Macro
\newcommand{\maketab}[2]{%
\begin{tabular}{#1}
                #2
\end{tabular}
}

%% Table Body
\newcommand{\tableBody}{
Short label & Very long description & Three letter label \\ 
  \hline
  1 &   5 &   9 \\ 
    2 &   6 &  10 \\ 
    3 &   7 &  11 \\ 
    4 &   8 &  12 \\ 
   \hline
}

%% and... 
\expandafter\maketab\colDef{\tableBody}

\end{document}

通过 Latexing 可以获得标签的预期结果:

Short   Very   long     Three
label   description     letter
                        label
-----------------------------
1       5               9
2       6               10
3       7               11
4       8               12
-----------------------------

R/knitr 方面

由于 tex.stackexchange 上有knitrxtable标签,我认为生成上述 LaTeX 的 R 代码可能会引起某些人的兴趣。

“编织”的 Rnw 文档是:

\documentclass{article}
\usepackage{varwidth, calc}     
\begin{document}

<<label=ididit, results='asis', echo=FALSE>>=

library(xtable) 

## Generate sample 4x3 table, with long labels
## -------------------------------------------

tab=data.frame(matrix(1:12, ncol=3))
names(tab) = c("Short label", "Very long description", "Three letter label")

## Generate LaTeX code: every \ needs to be doubled (escaped) 
## -----------------------------------------------------------

## Print LaTeX vars
cat("
\\def\\colDef{} 
\\newlength{\\temp}
")

## Dynamic text
text1="\\setlength{\\temp}{\\widthof{\\mbox{\\begin{varwidth}{\\textwidth}"
      # Labels here separated by // 
text2="\\end{varwidth}}}}
\\edef\\colDef{\\colDef p{\\the\\temp}}
"

## Separate labels with \\\\
lab= strsplit(names(tab), " ")
lab= sapply(lab, function(x) paste(x, collapse='\\\\'))

## Replace dynamic text with labels and print it
text=paste(text1, lab, text2, sep="\n", collapse="\n")
cat(text)
cat("\n\\edef\\colDef{{\\colDef}}")

## Setup main table macro 
cat("
\\newcommand{\\maketab}[2]{%
\\begin{tabular}{#1}
                #2
\\end{tabular}
}
")

## Table body obtained via xtable module
cat("\\newcommand{\\tableBody}{\n")
print.xtable(xtable(tab), only.contents=T, include.rownames=F)
cat("}\n")

###  eventually... 
cat("\\expandafter\\maketab\\colDef{\\tableBody}")

@ 

\end{document}

假如这个文档名为table.rnw,则将其编织起来,也就是在 R 中执行:

knitr("table.rnw")

将生成table.tex类似上面第一个清单中所示的 LaTeX 代码(加上一些用于图形的 knitr 宏修饰)在 LaTeX 中进行编译以获得所需的表格输出。

对解决方案的评论

请注意,所提出的解决方案需要在 R 中执行一步 + 在 LaTeX 中执行一步,因为生成的 LaTeX 包含用于测量长度和在表格环境中使用长度的代码。xtable仅用于生成表格内部单元格的格式化列表,因此人们可以轻松地使用一些更花哨的东西定制表格环境和/或为表格设置更多格式化参数。

避免从 R 到 LaTeX 的额外往返意味着速度,无论如何都建议任何进一步改进它的途径。

相关内容