据我所知,R+tikDevice+LaTex+knitr 是从 R 中获取美观出版物的最有效方法,同时还能从 LaTeX 中获得最大程度的布局支持。
我现在正在使用 R+LaTex+knitr,但想让 LaTex 更好地管理字体大小、分辨率和图的比例,因此 tikzDevice 0.7.0 似乎是最佳选择。这里有一个与此有些相关的问题,但(我认为)在 knitr+tikzDevice 0.7.0 之前已经回答过了:有关图形尺寸的最佳实践
但是我尝试使用 tikzDevice 的所有尝试都使其变得更加复杂,所以我担心我错过了一些基本的东西。可能是关于图的大小定义的位置。
以下示例尝试绘制相同的内容三次:首先不使用 tikzDevice,然后使用两种 tikzDevice 方式。tikzDevice 幻灯片看起来不太好看,我可以通过操作宽度和高度来改善。但我已经在 LaTex 中定义了 column-with,所以我不需要做更多,对吧?
\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\title{Beamer with 2+1 plots}
\author{Chris}
<<data.prep, include=FALSE>>=
library(ggplot2)
library(tikzDevice)
options(tikzDefaultEngine='xetex')
plot.data <- data.frame(days=c(1,2,3,4,5,6,7,8,9), price=c(2,3,4,3,5,6,5,7,8))
@
\begin{frame}{2+1 Plots (no Tikz)}
\begin{columns}
\begin{column}[t]{0.40\textwidth}
<<plot1, dev='pdf', fig.width=6, fig.height=5, dpi=144, echo=FALSE, message=FALSE, warning=FALSE, cache=FALSE>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
<<plot2, dev='pdf', fig.width=6, fig.height=5, dpi=144, echo=FALSE, message=FALSE, warning=FALSE, cache=FALSE>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\begin{column}[t]{0.58\textwidth}
<<plot3, dev='pdf', fig.width=8, fig.height=9, dpi=144, echo=FALSE, message=FALSE, warning=FALSE, cache=FALSE>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\end{columns}
\end{frame}
\begin{frame}{2+1 Plots (Tikz Attempt 1)}
\begin{columns}
\begin{column}[t]{0.40\textwidth}
<<plot4, results='hide', echo=FALSE, message=FALSE, warning=FALSE>>=
tikz("TikzAttempt1.tex",width=1.8,height=1.6)
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
dev.off()
@
\input{TikzAttempt1.tex}
<<plot5, results='hide', echo=FALSE, message=FALSE, warning=FALSE>>=
tikz("TikzAttempt2.tex",width=1.8,height=1.6)
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
dev.off()
@
\input{TikzAttempt2.tex}
\end{column}
\begin{column}[t]{0.58\textwidth}
<<plot6, results='hide', echo=FALSE, message=FALSE, warning=FALSE>>=
tikz("TikzAttempt3.tex",width=2,height=3)
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
dev.off()
@
\input{TikzAttempt3.tex}
\end{column}
\end{columns}
\end{frame}
\begin{frame}{2+1 Plots (Tikz Attempt 2)}
\begin{columns}
\begin{column}[t]{0.40\textwidth}
<<plot7, echo=FALSE, dev='tikz', fig.width=6, fig.height=5, out.width='.40\\paperwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
<<plot8, echo=FALSE, dev='tikz', fig.width=6, fig.height=5, out.width='.40\\paperwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\begin{column}[t]{0.58\textwidth}
<<plot9, echo=FALSE, dev='tikz', fig.width=8, fig.height=9, out.width='.58\\paperwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\end{columns}
\end{frame}
\end{document}
图的大小应该在哪里定义?在 chunk-definition 中?在 tikz-definition 中?在 LaTex input-definition 中?还是在 LaTex 中的 includegraphics-settings 中?
这两种 tikzDevice 方式哪一种最好使用?
我的演示文稿有许多带有情节的幻灯片,通常最终会得到 10MB 以上的 pdf 文件,希望通过 Tikz 可以降低文件大小。
由于字体原因,编译必须使用 XeLatex 完成。
Markdown 在这里不是一个选项,因为我需要做只有 LaTex 才能做的事情(未包含在示例中)。
答案1
这篇文章相当长。我将尝试回答你的两个主要问题。
抱歉,小说……
问题 1
以下示例尝试绘制同一件事三次:首先不使用 tikzDevice,然后使用两种 tikzDevice 方式。tikzDevice 幻灯片看起来不太好看,我可以通过操纵宽度和高度来改善。但我已经在 LaTex 中定义了 column-with,所以我不必做更多,或者?应该在哪里定义绘图的大小?在 chunk-definition 中?在 tikz-definition 中?在 LaTex input-definition 中?还是在 LaTex 中的 includegraphics-settings 中?
的作用beamer
让我们先从逆向思考开始。这个答案将首先清理你的“2+1 图(Ti钾Z 尝试 2)”。第二次尝试效果不佳的原因很大程度上是由于beamer
你的 LaTeX 代码,与 无关knitr
。
下面我将讨论字体大小knitr
。(如果您希望立即转到那里,请向下滚动到标题“带有knitr
”的字体大小。)
chunk
选项knitr
首先,重要的是要了解chunk
选项fig.height
、fig.width
和out.width
的作用。根据 Yihui 的这些选项的文档,fig.height
并fig.width
设置图形的高度和宽度R
以英寸来算。默认值为 7 英寸,传递给这些选项的值必须是数字。另一方面,out.width
(和out.height
)设置图形的宽度(和高度)就像最终输出文件中显示的那样。因此,这些值可以不同。如果这些尺寸不同,则最终输出文件中的图形将相应缩放。
现在,让我们看看你的第二个 Ti 的使用情况beamer
及其环境钾Z 尝试。
LaTeX 宽度 &beamer
这需要和朋友们讨论一下\textwidth
。@egreg回答到有关图形尺寸的最佳实践对此提供了一些很好的讨论。简而言之,
\textwidth
通常是文本区域的全局宽度[...]但是在或里面minipage
,\parbox
将与、和\textwidth
一起设置为给定的参数(它们将在形成组的或的末尾恢复为先前的值)。\hsize
\columnwidth
\linewidth
minipage
\parbox
我不熟悉beamer
内部结构,但columns
环境必须使用minipage
或,\parbox
因为环境\textwidth
内部columns
设置为列的总宽度,不是全局文本区域的总宽度。
因此,我们可以将 传递out.width='1\\textwidth'
给chunk
,这将防止您的图表溢出页面。\paperwidth
设置为整个页面的宽度,包括任何边距。这就是为什么您的图表在第二次尝试时似乎溢出页面的原因。
因此:
\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\title{Beamer with 2+1 plots}
\author{Chris}
<<data.prep, include=FALSE>>=
library(ggplot2)
library(tikzDevice)
options(tikzDefaultEngine='xetex')
plot.data <- data.frame(days=c(1,2,3,4,5,6,7,8,9), price=c(2,3,4,3,5,6,5,7,8))
@
\begin{frame}{2+1 Plots (Tikz Attempt 3)}
\begin{columns}[onlytextwidth]
\begin{column}[t]{0.40\textwidth}
<<plot10, echo=FALSE, dev='tikz', fig.width=6, fig.height=5, out.width='1\\textwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
<<plot11, echo=FALSE, dev='tikz', fig.width=6, fig.height=5, out.width='1\\textwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\begin{column}[t]{0.58\textwidth}
<<plot12, echo=FALSE, dev='tikz', fig.width=8, fig.height=9, out.width='1\\textwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\end{columns}
\end{frame}
\end{document}
生成:
(笔记:我已将选项传递onlytextwidth
给columns
环境。请参阅@Werner 的讨论,他的回答到Beamer 中带有图像和换行文本的多列)
以一个图表为例,此幻灯片上最右边的图表由 制作而成,R
宽度为 8 英寸,高度为 9 英寸。然后,LaTeX 获取此图形并将其缩放,使其宽度为1\textwidth
,在本例中,它正好是最右边列的宽度。
现在,这些图表中的字体显然仍然很小,让我们看看可以做些什么来解决这个问题。
字体大小knitr
有记录TikZDevice
,我强烈建议您阅读它。不过,我会尝试将文档中的所有字体信息提炼为可用的格式。
计算字体大小
LaTeX 中的字体大小是根据基本字体大小指定的。因此,当您声明 时\documentlcass[10pt]{beamer}
,所有字体大小的变化都是相对于该基本字体大小计算的,并且不能通过类似以下方式轻松指定24pt
。Ti钾Z 通过缩放文本来处理这个问题;缩放因子是相对于基本字体大小计算的(参见文档了解更多信息)。
在谈论如何然而,要设置字体大小,我们必须真正了解缩放因子是如何计算的。
根据文档,缩放因子等于cex
*( ps
/ base font size
),其中cex
和ps
设置在 中R
。
(我不太熟悉R
这些是如何设置的。根据阅读TikZDevice
文档,我随意猜测这些必须以某种方式通过ggplot2
via来设置par
。至少,?par
如果你想尝试弄清楚的话,这似乎是开始的地方。但我真的不知道。)
但重点是,是分母base font size
。因此,字体越小,base font size
实际越大。
使用设置字体大小knitr
那么我们如何设置这个基本字体大小呢?如果你使用第一种tikz()
直接调用的方法,你可以在调用中设置它tikz()
:
tikz(<other arguments>, pointsize=10)
出于下面将要讨论的原因,我更喜欢您的其他方法。pointsize
即使我们没有tikz()
直接调用,我们仍然可以以这种方式设置。knitr
提供了一个设备挂钩,因此我们可以将其用作dev.args=list(pointsize=10)
选项chunk
。
以下是展示一些不同字体大小的 MWE:
\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\title{Beamer with 2+1 plots}
\author{Chris}
<<data.prep, include=FALSE>>=
library(ggplot2)
library(tikzDevice)
options(tikzDefaultEngine='xetex')
plot.data <- data.frame(days=c(1,2,3,4,5,6,7,8,9), price=c(2,3,4,3,5,6,5,7,8))
@
\begin{frame}{2+1 Plots (Tikz Attempt 4)}
\begin{columns}[onlytextwidth]
\begin{column}[t]{0.40\textwidth}
Too big!
<<plot13, echo=FALSE, dev='tikz', dev.args=list(pointsize=0.9), fig.width=6, fig.height=5, out.width='1\\textwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
Pretty big!
<<plot14, echo=FALSE, dev='tikz', dev.args=list(pointsize=2), fig.width=6, fig.height=5, out.width='1\\textwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\begin{column}[t]{0.58\textwidth}
Reasonable.
<<plot15, echo=FALSE, dev='tikz', dev.args=list(pointsize=6), fig.width=8, fig.height=9, out.width='1\\textwidth'>>=
p <- ggplot(plot.data, aes(x=days, y=price))
p <- p + geom_line()
p
@
\end{column}
\end{columns}
\end{frame}
\end{document}
因此,您可以根据自己的喜好调整pointsize
(设置所base font size
使用的TikZDevice
)。
问题2
这两种 tikzDevice 方式哪一种最好使用?
为了回答您的第二个问题,我更喜欢您使用的后一种方法。这是因为图表是作为其自己的 PDF 生成的,然后通过 LaTeX 输出呈现的\includegraphics
。如果您将您的作品提交给需要单独 PDF 文件的出版商,这可能会很有利,例如,因为他们无法在自己的机器上编译您的图像。
另一方面,你以前的方法\input{}
是 Ti钾Z 代码。这样做的好处是,您可以轻松操作 Ti钾Z 代码,无论出于何种原因。如果这是您需要做的事情,您可能希望阅读提供的bareBones
方法TikZDevice
。请参阅第 12-15 页文档。