图表

Quarto 包含许多功能,旨在使图表和子图表的使用更加简便,同时也便于布局包含多个图表、表格或其他内容的面板。

图表基础

在 Pandoc Markdown 中,每当一个带有标题的图像独自出现在段落中时,就会创建一个图表。例如:

![大象](elephant.png)

这在不同输出类型中会呈现如下效果:

HTML PDF Word
一只大象的线条画。 一只大象的线条画。 一只大象的线条画。

请注意,对于 LaTeX / PDF 输出,图表会自动编号(你可以使用交叉引用在其他格式中安排图表编号)。

图表尺寸

默认情况下,图表会以其实际尺寸显示(受限于其渲染的页面宽度约束)。你可以通过为图表添加 widthheight 属性来改变显示尺寸。例如:

![大象](elephant.png){width=300}

请注意,如果仅指定 width,则 height 会自动计算。如果你需要修改默认行为,只需添加一个显式的 height 属性。

widthheight 的默认单位是像素。你也可以使用百分比或常规测量单位如英寸或毫米来指定尺寸。例如:

![大象](elephant.png){width=80%}
![大象](elephant.png){width=4in}

链接图表

在 Quarto 渲染时,你可以将图表嵌入链接中,它仍会在输出中被视为带有标题的图表。例如:

[![大象](elephant.png)](https://en.wikipedia.org/wiki/Elephant)

图表对齐

图表默认居中对齐。为图像添加 fig-align 属性以使用不同的对齐方式。例如:

![大象](elephant.png){fig-align="left"}

请注意,图表标题默认左对齐以适应较长的标题文本(居中对齐时看起来很奇怪)。

替代文本

你可以通过为图像添加 fig-alt 属性来为图表添加替代文本。例如,以下 Markdown…

![](elephant.png){fig-alt="一只大象的画作。"}

…会生成带有相应 alt 标签的以下 HTML:

<img src="elephant.png" alt="一只大象的画作。">

请注意,图表标题、标题和替代文本可以各不相同。例如,以下代码…

![大象](elephant.png "标题:一只大象"){fig-alt="一只大象的画作。"}

…会生成以下 HTML:

<img src="elephant.png" title="标题:一只大象" alt="一只大象的画作。">

要渲染标题而不是替代文本,可以按照Pandoc 文档中的详细说明,在行尾添加反斜杠:

![一只大象的画作。](elephant.png)\

多格式图表

你可以编写 Markdown,根据目标输出格式提供不同的图像文件格式。为此,只需省略扩展名,例如:

![](elephant)

默认情况下,这将查找 elephant.png,但如果你渲染为 PDF,则会查找 elephant.pdf。你可以使用 default-image-extension 选项自定义此行为。例如:

format:
  html:
    default-image-extension: svg
  pdf:
    default-image-extension: tex

灯箱图表

在 HTML 输出格式中,你可以为图像添加灯箱样式和行为,以便读者点击查看图像的更大版本。例如,以下图像是灯箱处理过的(点击图像查看灯箱效果):

一只大象

一只大象

可以通过为图像添加类 .lightbox 来添加灯箱处理:

![一只大象](elephant.png){.lightbox}

有关更多详细信息和其他启用和禁用灯箱处理的方法,请参阅灯箱图表

应用多个参数

要结合上述方法,请用空格分隔参数,例如:

![](elephant.png){fig-alt="一只大象的画作。" fig-align="left" width=20%}

你可以通过为图表添加带有 fig- 前缀的 ID 来进行交叉引用,然后使用 @ 前缀来引用该图表。例如:

![一只大象](elephant.png){#fig-elephant}

这一点通过 @fig-elephant 可以很好地说明。

对于由可执行代码单元格生成的图表,请包含一个带有 fig- 前缀的 label,以便能够交叉引用它们。例如:

关于折线图的演示,请参见 @fig-line-plot。

```{python}
#| label: fig-line-plot
#| fig-cap: "一条折线图"

import matplotlib.pyplot as plt
plt.plot([1,23,2,4])
plt.show()
```
标签前缀

为了让一个图表能够被交叉引用,其标签必须以 fig- 前缀开头。

更多详情请参阅交叉引用文章。

子图表

如果你有一组多个图表,可以将它们放在一个图表 div 中。例如:

::: {#fig-elephants layout-ncol=2}

![Surus](surus.png){#fig-surus}

![Hanno](hanno.png){#fig-hanno}

著名的大象
:::

同样,最后一个段落提供主标题,而各个图表带有子标题。以下是渲染为 HTML 时的效果:

左边的艺术再现了Surus,汉尼拔最后一只战争大象,图片下方是标题‘(a) Surus’。右边是一只著名大象Hanno的线条画,图片下方是标题‘(b) Hanno’。两个图片下方居中显示‘图1:著名的大象’。

请注意,图表之间的空行(以及最后一个图表和标题之间的空行)是必需的(这表明这些图像是属于它们自己的段落,而不是同一段落中的多个图像)。

还要注意,我们也使用了 layout-ncol 属性来指定一个两列布局。下一节将深入探讨自定义图表布局。

图表面板

在上文中,我们展示了如何布局带有子标题和主标题的两个并排图表。你可能不需要标题/子标题的处理,或者你可能想要使用多行图表。所有这些变体都是可能的。

要布局两个带有独立标题的图表(并且没有主标题),只需去掉 #fig 标识符和底部的标题:

::: {layout-ncol=2}
![Surus](surus.png)

![Hanno](hanno.png)
:::

左边是一幅艺术再现的Surus,汉尼拔最后一只战争大象,图片下方是标题‘Surus’。右边是一只著名大象Hanno的线条画,图片下方是标题‘Hanno’。

你也可以完全去掉标题:

::: {layout-ncol=2}
![](surus.png)

![](hanno.png)
:::

多行

如果你有超过两个图像,可能希望将它们分布在多行中。你可以使用 layout-nrow 属性来实现这一点。例如:

::: {layout-nrow=2}
![Surus](surus.png)

![Hanno](hanno.png)

![Abdul Abbas](abdul-abbas.png)

![Lin Wang](lin-wang.png)
:::

一个2x2的网格,包含四只大象的图片。每张图片下方都有标签。从左上角顺时针方向,标签依次为:Surus、Hanno、Lin Wang和Abdul Abbas。

更复杂的图表排列(例如,不同列布局的行)也是可能的。更多详情请参阅下面的自定义布局部分。

图表 Div

你可以将任何你想作为图表的 Markdown 内容包含在带有 #fig- 前缀标识符的 Pandoc div 块中。例如,这里我们创建了一个包含嵌入 iframe 的图表:

::: {#fig-elephant}

<iframe width="560" height="315" src="https://www.youtube.com/embed/SNggmeilXDQ"></iframe>

大象
:::

请注意,div 块中的最后一个段落被用作图表标题。

LaTeX 图表

本节描述一些特定于 LaTeX 输出的图表处理选项。

需要注意的一个非常重要的事情是,使用下面描述的 fig-envfig-pos 选项将触发 LaTeX 浮动环境的创建(最常见的是 \begin{figure})。根据 LaTeX 生成的位置(例如,在另一个 \begin{figure} 内部),这可能会产生无效的 LaTeX。为了安全起见,这些属性通常只应在文档的最顶层图像中使用。

环境

有许多 LaTeX 包提供自定义的图表环境。例如,在两栏格式中,figure* 环境跨越文档的两列。你可以通过将图表环境作为图像或围栏 div 的 fig-env 属性显式传递来使用。

![大象](surus.jpg){#fig-elephant fig-env="figure*"}

::: {#fig-elephant-2 fig-env="figure*"}

![](surus.jpg)

另一只大象。

:::

图片位置

默认的 LaTeX figure 是一个浮动环境,因此它在文档中出现的具体位置将取决于其大小以及周围内容的情况。你可以使用 fig-pos 选项对这种行为进行一些控制。fig-pos 选项为 figure 环境提供了一个位置说明符。例如,以下 LaTeX 代码片段中的 ht 就是 fig-pos

\begin{figure}[ht]

\end{figure}

你可以在文档级别、作为可执行代码块选项或在 Markdown 中指定 fig-pos。这里我们全部三种方式都使用了:

---
title: "我的文档"
format:
  pdf:
    fig-pos: 'h'
---

```{python}
#| fig-pos: 't'

```

![](figure.png){fig-pos='b'}

有关 LaTeX 图片定位的更多细节,请参阅这篇文章

图片和代码块

如果你的图片是由可执行代码块生成的,并且代码包含在输出中(echo: true),那么 fig-pos 将默认设置为 H(以尝试将其保持在生成它的代码旁边)。在所有其他情况下,除非你明确指定 fig-pos,否则将使用默认的 LaTeX 图片位置处理。

简短标题

你可以使用 fig-scap 选项提供一个在“图片列表”中使用的简短标题。你可以在可执行代码块选项中或作为图片属性指定 fig-scap

```{python}
#| fig-cap: "长标题"
#| fig-scap: "短标题"

```

![长标题](figure.png){fig-scap='短标题'}

PGF/TikZ 图形

如果你正在创建 LaTeX 输出,Quarto 会自动为引用包含 PGF/TikZ 矢量图形的 .tex 文件的 Markdown 图片生成正确的 LaTeX 代码。例如,以下 Markdown 图片:

![](image1.tex)

![](image2.tex){width=80%}

将被写入 LaTeX 为:

\input{image1.tex}

\resizebox{0.8\linewidth}{!}{\input{image2.tex}}

如上所示,widthheight 的百分比会自动转换为按 \linewidth 缩放。或者,你可以为 \resizeboxwidthheight 参数指定自定义的 LaTeX。

标题位置

默认情况下,图片标题位于图片下方。在 HTML 和 PDF 格式中,你可以使用 fig-cap-location 选项修改此行为。例如:

---
fig-cap-location: top
---

请注意,此选项在顶层指定,以便它可以被 PDF 和 HTML 格式共享。如果你只针对单一格式,可以将其与其他特定于格式的选项放在一起。

标题位置的有效值包括:

描述
top 将标题置于图片上方。
bottom 将标题置于图片下方。
margin 将标题置于页边距中。

有关在页边距中放置标题的更多细节,请参阅文章布局

自定义布局

上面的示例使用了 layout-ncollayout-nrow 属性来创建所有列大小相等的简单布局。layout 属性可以创建更复杂的布局。

例如,这定义了一个布局,第一行有两个大小相等的图片,然后另一张图片占据了整个第二行:

::: {layout="[[1,1], [1]]"}
![Surus](surus.png)

![Hanno](hanno.png)

![Lin Wang](lin-wang.png)
:::

三张大象图片排列成两行,第一行有两张图片并排,第二行有一张图片,宽度与高度相当于前两张图片的总和。第一行左边的图片标题为'Surus',右边的图片标题为'Hanno'。第二行的图片标题为'Lin Wang'。

layout 属性是一个二维数组,其中第一个维度定义行,第二个维度定义列。在这种情况下,"layout="[[1,1], [1]]" 翻译为:创建两行,第一行有两个大小相等的列,第二行有一个单独的列。

请注意,行中的数字是任意的,不需要加起来达到特定总数。因此,你可以使用最自然的方案。例如,这里我们定义了占据行不同百分比宽度的列:

::: {layout="[[70,30], [100]]"}
![Surus](surus.png)

![Hanno](hanno.png)

![Lin Wang](lin-wang.png)
:::

你也可以使用负值在元素之间创建空间。例如:

::: {layout="[[40,-20,40], [100]]"}
![Surus](surus.png)

![Hanno](hanno.png)

![Lin Wang](lin-wang.png)
:::

三张大象图片排列成第一行两张并排,第三张在它们下方。第一行左侧图片标注为'Surus',右侧图片标注为'Hanno'。两张图片之间有一些空白。下方的图片标注为'Lin Wang',比其他两张图片加起来还要宽和高。

垂直对齐

如果你有一个包含不同高度图片的布局,你可以使用 layout-valign 属性来控制它们的垂直对齐方式。一个简单的例子:

::: {layout="[15,-2,10]" layout-valign="bottom"}
![Surus](surus.png)

![Lin Wang](lin-wang.png)
:::

两张大象图片并排。左边图片下方标注为'图1:Surus'。右边图片下方标注为'图2:Lin Wang'。左边的图片是右边图片宽度和高度的两倍以上。

请注意,垂直对齐不仅限于图片,你还可以对包含在面板中的任何其他元素进行垂直对齐。

计算

由可执行代码块生成的图表会自动包含在你的文档中。要设置ID、标题和链接,分别使用 labelfig-capfig-link 选项。其他属性,例如 fig-alignfig-alt,可以使用同名的选项进行设置。

你可以使用文档头部的 fig-widthfig-height 选项来控制计算图表的默认大小。更多关于这些选项的信息,请参阅执行选项:图表选项

布局

请注意,图表布局属性同样适用于由可执行代码块生成的图表。以下是 Jupyter 和 Knitr 的示例:

```{python}
#| layout-ncol: 2
#| fig-cap: 
#|   - "线图1"
#|   - "线图2"

import matplotlib.pyplot as plt
plt.plot([1,23,2,4])
plt.show()

plt.plot([8,65,23,90])
plt.show()
```

Jupyter 生成的两个并排的线图。

```{r}
#| layout-ncol: 2
#| fig-cap: 
#|   - "汽车的速度和停车距离"
#|   - "汞的蒸汽压作为温度的函数"

plot(cars)
plot(pressure)
```

两个并排的散点图。

请注意,在这些示例中,我们还使用了 fig-cap 选项为生成的每个图表添加标题。

子标题

你可以通过结合使用 fig-capfig-subcap 选项为计算输出创建子标题。当为计算输出添加标题时,你可以选择性地包含一个带有 fig- 前缀的 label——如果你这样做,那么图表将被编号并可交叉引用

```{python}
#| label: fig-charts
#| fig-cap: "图表"
#| fig-subcap: 
#|   - "第一"
#|   - "第二"
#| layout-ncol: 2

import matplotlib.pyplot as plt
plt.plot([1,23,2,4])
plt.show()

plt.plot([8,65,23,90])
plt.show()
```

Jupyter 生成的带有标题的两个并排线图。

```{r}
#| label: fig-charts
#| fig-cap: "图表"
#| fig-subcap: 
#|   - "汽车"
#|   - "压力"
#| layout-ncol: 2

plot(cars)
plot(pressure)
```

带有标题的两个并排散点图。

自定义布局

layout 选项对于 Knitr 或 Jupyter 生成的图表的工作方式相同。例如,这是一个生成 3 个图表并为它们定义自定义布局的 Rmd 代码块:

```{r}
#| layout: [[45,-10, 45], [100]]

plot(cars)
plot(pressure)
plot(mtcars)
```

两个图表并排排列,下方有一个大图表。顶部两个图表是散点图,分别可视化了 `cars` 和 `pressure` 数据集。这两个图表之间有一些额外的空白。底部的图表可视化了 `mtcars` 数据集,比其他两个图表加起来还要宽和高。这个图表是一个 11x11 的网格,绘制了 `mtcars` 数据集中的每个变量作为散点图。从左上到右下的对角线上不是散点图,而是每个变量名称的文本标签。这些是:'mpg', 'cyl', 'disp', 'hp', 'drat', 'wt', 'qsec', 'vs', 'am', 'gear', 和 'carb'。

块布局

尽管上面的示例说明了图表的布局,但重要的是要注意布局属性可以用于布局任何类型的块内容。例如,这里我们将两个列表并排布局:

::: {layout-ncol=2}
### 列表一

- 项目A
- 项目B
- 项目C

### 列表二

- 项目X
- 项目Y
- 项目Z
:::

注意标题会自动与后面的内容块合并,因此这个markdown总共有2列用于布局。以下是一个段落与一个项目符号列表并列的示例(无标题):

::: {layout-ncol=2}
- 项目 X
- 项目 Y
- 项目 Z

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur gravida eu erat et fring. Morbi congue augue vel eros ullamcorper, eget convallis tortor sagittis. Fusce sodales viverra mauris a fringilla. Donec feugiat, justo eu blandit placerat, enim dui volutpat turpis, eu dictum lectus urna eu urna. Mauris sed massa ornare, interdum ipsum a, semper massa. 
:::

对于更复杂的内容,使用div(:::)将内容划分为块以便布局。例如,以下是如何将代码单元与一些文本并列,旁边放置一个图形的示例:

:::: {layout="[ 40, 60 ]"}

::: {#first-column}
```r
# 一些代码
```

一些应该在代码下方布局的文本
:::

::: {#second-column}
![](elephant.png)
:::

::::

id属性(#first-column#second-column)是可选的,但有助于提高可读性。