撰写手稿

概述

在本页中,我们将向您展示如何在Jupyter Lab中使用Quarto撰写学术手稿。您将学习如何:

  • 使用Jupyter Lab预览您的手稿。

  • 添加学术前言以描述您的文章。

  • 使用Quarto特定的Markdown添加图表、表格、交叉引用和引用。

  • 使用内联代码或从外部笔记本嵌入包含计算结果。

您将学习的命令和语法适用于任何编辑笔记本的工具,而不仅仅是Jupyter Lab。而且,尽管我们将使用Python代码示例,但Quarto适用于任何内核,因此您也可以使用R或Julia。

本教程适合我吗?

我们将假设您:

  • 能够使用Jupyter Lab打开和编辑文件,
  • 拥有GitHub账户,并且能够将仓库克隆到您的计算机上,
  • 能够浏览文件系统,并在终端中执行命令。

设置

要继续学习,您需要安装 Jupyter Lab Quarto 扩展并克隆模板仓库。

首先安装 Quarto

如果您还没有安装,请确保您已安装最新版本的 Quarto,如 手稿概述 中所述。

安装 Jupyter Lab Quarto 扩展

安装取决于您使用的 JupyterLab 版本:

您可以通过以下两种方式之一安装 Quarto JupyterLab 扩展:

  1. 在 JupyterLab UI 中:在扩展管理器中搜索 ‘Quarto’ 并安装 jupyterlab-quarto 扩展。完成后,系统会提示您刷新页面。

    Jupyter Lab 扩展管理器的屏幕截图,搜索框中输入了 'quarto',并显示了一个名为 'jupyterlab-quarto' 的搜索结果。

  2. 使用 pip

    平台 命令
    Mac/Linux
    Terminal
    python3 -m pip install jupyterlab-quarto
    Windows
    Terminal
    py -m pip install jupyterlab-quarto

您可以通过以下两种方式之一安装 Quarto JupyterLab 扩展:

  1. 使用 pip,您可以通过执行以下命令安装 jupyterlab-quarto

    平台 命令
    Mac/Linux
    Terminal
    python3 -m pip install jupyterlab-quarto==0.1.45
    Windows
    Terminal
    py -m pip install jupyterlab-quarto==0.1.45

    这是安装 JupyterLab Quarto 扩展的首选方式,因为它利用了传统的 Python 打包方式,并且不需要重新构建 JupyterLab 即可完成安装。

  2. 在 JupyterLab UI 中,您可以直接使用扩展管理器搜索 ‘Quarto’ 并安装 @quarto/jupyterlab-quarto 扩展。要完成安装,您需要重新构建 JupyterLab(安装 Quarto 扩展后,您应该会看到一个提示来完成此操作)。

克隆模板仓库

要跟随本教程,您需要拥有 模板仓库 的副本,包括其所有分支。

  1. 前往 GitHub 从模板创建新仓库

    提供一个 仓库名称 并确保勾选 包含所有分支。然后 从模板创建仓库GitHub 从模板创建新仓库页面的截图。仓库名称已填写为 manuscript-template,并且标记为包含所有分支的框已勾选。

  2. 仓库创建完成后,将其克隆到您的本地计算机。

    您可以以任何您熟悉的方式进行,例如在终端中,可能看起来像这样:

    终端
    git clone git@github.com:<用户名>/<仓库名>.git

    其中您使用自己的用户名和仓库名。

  1. 您将在整个教程中在此目录内工作,因此如果您准备好继续,请导航到该目录并启动 Jupyter Lab:

    终端
    cd manuscript-tutorial
    python3 -m jupyter lab

Jupyter Lab 的截图。文件浏览器打开,显示文件夹:_extensions, images, 和 notebooks;以及文件:_quarto.yml, index.ipynb, README.md 和 references.bib。

在 Jupyter Lab 中打开的模板手稿

项目文件

最简单的 Quarto 手稿项目包含两个文件:

  • 一个笔记本文件,你在这里撰写文章:index.ipynb。该文件包含:
    • 文档元数据,包括文章的前置信息(作者、所属机构等)和 Quarto 选项,
    • 文章正文,使用特殊的 Quarto Markdown 语法编写,允许你添加交叉引用和引用等内容,
    • 可选地,代码部分,你可以控制代码及其输出是否或如何出现在文章中。
  • 一个配置文件 _quarto.yml,用于标识该项目为 Quarto 手稿,并控制手稿的组合方式。

这个特定的手稿项目还包括一些其他文件和文件夹,你将在本教程中逐步了解这些文件。

工作流程

使用 Quarto 编写手稿的基本工作流程是在 index.ipynb 中修改文章内容,使用 Quarto 预览更改,并重复此过程。让我们来试试。

在 Jupyter Lab 中打开一个新的终端并运行:

Terminal
quarto preview

你会在终端上看到 Quarto 的一些输出:

Terminal
$ quarto preview
准备预览
[1/1] index.ipynb

监视文件更改
浏览地址:http://localhost:3806/
GET: /

然后,浏览器窗口将打开,显示手稿的实时预览。

你可能会发现移动和调整窗口大小以便 Jupyter Lab 和实时预览并排显示很有帮助。

两个并排的浏览器窗口截图。左边是 Jupyter Lab,终端打开显示命令:quarto preview。右边是一个网页,地址以 localhost: 开头,内容以标题 La Palma Earthquakes 开头。

文章的内容由 index.ipynb 生成。继续在 Jupyter Lab 中打开此文件。

两个并排窗口的截图。左边是 Jupyter Lab,文件 `index.ipynb` 打开。第一个单元格以标题 La Palma Earthquakes 开头。右边是一个网页,地址以 localhost: 开头,内容以标题 La Palma Earthquakes 开头。

接下来你将深入了解这个文件的细节,但现在让我们先做一个更改,看看会发生什么。

第一个单元格(以 “La Palma Earthquakes” 开头)是一个 Markdown 单元格,进入此单元格的编辑模式,并找到以下行:

title: La Palma Earthquakes

将该行更改为:

title: La Palma Earthquake Mechanisms

保存笔记本,你会看到预览自动更新。

两个浏览器窗口的截图。左边是 Jupypter Lab,文件 index.ipynb 打开,第一个单元格处于编辑模式,文本为 title: La Palma Earthquake Mechanisms。右边是文章网页,标题为 La Palma Earthquake Mechanisms。

Tip

如果你不小心关闭了预览,可以通过终端输出的 URL 再次导航到它,例如 http://localhost:3806/。如果你想停止预览,在终端中按 Crtl + C。你可以通过再次运行 quarto preview 来重新启动预览。

笔记本结构

文件 index.ipynb 是一个 Jupyter Notebook。与任何 Jupyter Notebook 一样,它包含可以为原始内容、Markdown 或代码的单元格。这个 Notebook 有三个特定于 Quarto 的特性:

  • 第一个单元格包含一个 YAML 头,用于设置文档元数据,包括学术前言。这个单元格必须以三行破折号(---)开始和结束,在这些行之间,内容被解析为 YAML。你会注意到该单元格本身被设置为 Markdown 单元格;这使得 Quarto Jupyter Lab 扩展能够直观地模拟这些选项在渲染文档中的显示方式。

  • 其他 Markdown 单元格使用特定于 Quarto 的 Markdown 语法来包含图表、表格、方程、交叉引用和引用等内容。

  • 代码单元格的顶部可能有以 #| 开头的特殊 Quarto 注释。这些注释设置了控制代码及其输出在文章中显示方式的 Quarto 选项。

本页的其余部分将自上而下地引导你浏览本文中的单元格,向你介绍编写学术文章时最可能需要的 Quarto 功能。

前言

YAML 头部由使用 key: value 语法设置的键值对组成。由于用于指定大量的学术前言内容,如作者及其所属机构,以及摘要等,文章的头部通常较为广泛。

title: 拉帕尔马地震
author:
  - name: 史蒂夫·珀维斯
    orcid: 0000-0002-0760-5497
    corresponding: true
    email: steve@curvenote.com
    roles:
      - 调查
      - 项目管理
      - 软件
      - 可视化
    affiliations:
      - Curvenote
  - name: 罗恩·科基特
    orcid: 0000-0002-7859-8394
    corresponding: false
    roles: []
    affiliations:
      - Curvenote
keywords:
  - 拉帕尔马
  - 地震
abstract: |
  2021年9月,西班牙加那利群岛的拉帕尔马岛地震活动显著增加,标志着火山危机的开始,这一危机在撰写本文时仍在持续。地震数据由西班牙国家地理研究所(IGN)持续收集并发布。...
plain-language-summary: |
  2021年9月拉帕尔马岛火山喷发期间的地震数据发现...
key-points:
  - 开发了一个网络爬虫脚本,从西班牙国家地理研究所提取数据,以便进行机器可读的分析
  - 拉帕尔马岛的地震事件与地幔和地壳储层的活动一致。
date: last-modified
bibliography: references.bib
citation:
  container-title: 地球与空间科学
number-sections: true

例如,在 index.ipynb 的头部顶层设置了以下键:titleauthorkeywordsabstractplain-language-summarykey-pointsdatebibliographycitationnumber-sections

你已经看到,编辑 title 键会更新稿件网页上的文章标题。title 键也被 PDF 和 Word 格式使用,但并非所有键在所有格式中都被使用。

你可以在 Scholarly Front Matter 中阅读更多关于为你的文章设置前言的内容。

Markdown

文档中的Markdown单元格将由Quarto特定的Markdown语法处理。Quarto的Markdown语法基于Pandoc Markdown,而Pandoc Markdown又基于John Gruber的Markdown,这与Jupyter Notebooks使用的Markdown相同。

例如,创建文章介绍标题的Markdown语法是:

## Introduction

一级标题保留用于文章标题,因此您将使用二级及更深层次的标题来构建文章的各个部分。

如果对Markdown语法不熟悉,您可能需要阅读关于Quarto的Markdown基础

计算

Python 示例

本节使用 Python 代码示例,但 Quarto 也支持 R、Julia 和 Observable。

您不需要重新运行 Python 代码来跟随学习,但如果您愿意,您需要 matplotlibnumpy 包。

您的文章可以包含可执行代码。默认情况下,代码本身不会在文章中显示,但任何输出(包括表格和图表)都会显示。当您在文章中包含代码时,您还会在稿件网页的“笔记本”下获得一个额外的“文章笔记本”链接。这是包含代码的文章笔记本的渲染版本。

例如,index.ipynb 包含:

import matplotlib.pyplot as plt
import numpy as np
eruptions = [1492, 1585, 1646, 1677, 1712, 1949, 1971, 2021]

此代码不会出现在渲染的文章中,但会出现在“文章笔记本”中。

渲染文章的截图,其中有一个以 'Let x denote' 开头的部分。没有代码可见。

渲染的文章

文章笔记本的截图,其中有一个以 'Let x denote' 开头的部分。代码在两个单元格中可见。第一个单元格以 'import matplotlib' 开头。

文章笔记本

您可以通过在顶部添加 #| 注释,然后使用 YAML 语法添加 Quarto 选项。例如,添加 echo 选项并将其值设置为 true 将如下所示:

#| echo: true
import matplotlib.pyplot as plt
import numpy as np
eruptions = [1492, 1585, 1646, 1677, 1712, 1949, 1971, 2021]

echo 选项描述代码是否包含在渲染的文章中。如果您进行此更改并保存 index.ipynb,您将看到此代码现在出现在文章中。

您可以在 Jupyter 代码单元格 参考页面上找到所有可用的代码单元格选项的列表。

下一个代码单元格创建一个图表:

#| label: fig-timeline
#| fig-cap: La Palma 最近地震的时间线
#| fig-alt: La Palma 最近 8 次喷发的年份事件图。

plt.figure(figsize=(6, 1))
plt.eventplot(eruptions, lineoffsets=0, linelengths=0.1, color='black')
plt.gca().axes.get_yaxis().set_visible(False)
plt.ylabel('')
plt.show()

label 选项用于为代码单元格及其输出添加标识符,例如允许交叉引用。对于图表交叉引用,前缀 fig- 是必需的,但后缀(在本例中为 timeline)则由您决定。您将在下面了解更多关于 交叉引用 的信息。

选项 fig-cap 提供了在手稿中显示在图表下方的标题文本,而 fig-alt 则为图表提供了替代文本,有助于您的手稿网页符合可访问性指南。

计算也是基于数据包含表格的好方法。您可以在 Quarto 文档中阅读更多关于 基于计算的表格 的内容。

如果您有不想包含在文章中的代码输出,可以使用 output: false。例如,您可能有一个对编写内容有帮助的值,但您不希望它在文章中出现。下一个代码单元格是一个示例:

#| output: false
avg_years_between_eruptions = np.mean(np.diff(eruptions[:-1]))
avg_years_between_eruptions

如果您正在查看渲染后的“文章笔记本”,您会看到 avg_years_between_eruptions 的值显示在此代码下方,但该值不会出现在渲染后的文章中。

如果您希望排除单元格及其输出,使其既不在文章中也不在渲染的笔记本中出现,可以使用 include: false 代替:

#| include: false
avg_years_between_eruptions = np.mean(np.diff(eruptions[:-1]))
avg_years_between_eruptions

您还可以通过使用内联代码直接在文章文本中使用计算值。在 内联代码 中了解更多信息。

除了直接在文章中包含计算外,您还可以嵌入其他笔记本的输出,请在下面的 嵌入笔记本 中了解更多信息。

代码何时执行?

默认情况下,Quarto 不会在 .ipynb 笔记本中执行任何代码。如果您需要更新单元格输出,请运行相应的单元格并保存笔记本。

引用

文章引用

本节介绍如何在文章正文中添加引用。文章网页底部显示的引用信息通过前言进行控制。

要添加引用,您需要一个包含引用数据的参考文献文件(.bib)。您可以在文档 YAML 中使用 bibliography 选项指定此文件。例如,index.ipynb 的引用数据存储在 references.bib 中:

bibliography: references.bib

references.bib 文件仅包含一个引用:

references.bib
@article{marrero2019,
  author = {Marrero, Jos{\' e} and Garc{\' i}a, Alicia and Berrocoso, Manuel and Llinares, {\' A}ngeles and Rodr{\' i}guez-Losada, Antonio and Ortiz, R.},
  journal = {Journal of Applied Volcanology},
  year = {2019},
  month = {7},
  pages = {},
  title = {Strategies for the development of volcanic hazard maps in monogenetic volcanic fields: the example of {La} {Palma} ({Canary} {Islands})},
  volume = {8},
  doi = {10.1186/s13617-019-0085-5},
}

要在正文中引用参考文献中的文章,您可以使用 @ 后跟引用标识符,例如 marrero2019。例如,文章中包含引用此参考文献的这一行:

Studies of the magma systems feeding the volcano, such as @marrero2019, have proposed ...

这会呈现为:

Studies of the magma systems feeding the volcano, such as Marrero et al. (2019), have proposed …

将鼠标悬停在引用文本上会显示完整的参考文献详细信息。点击引用会将读者带到文章末尾的参考文献部分:

渲染后的文章截图,显示标题为 References 的部分。标题下方是一个完整的参考文献,开头为 'Marrero, José, '。

交叉引用

Quarto 可以生成交叉引用,自动为你管理编号和链接。交叉引用的通用语法是 @ 后面跟一个标签。例如,要引用时间线图,你可以写:

@fig-timeline

渲染时,交叉引用会包含一个词来指示被引用对象的类型,如“图”或“表”。因此,例如在 index.ipynb 中的这一行:

自15世纪末以来,已记录了八次喷发 (@fig-timeline)。

结果是:

自15世纪末以来,已记录了八次喷发(图1)。

其中“图1”也是一个指向相应图表的链接。

你添加到元素的标签必须有适当的标签前缀,以允许交叉引用:

元素 标签前缀 渲染的交叉引用
fig- 图1
tbl- 表1
方程 eq- 方程1
章节 sec- 章节1

你已经看到可以通过 label 代码块选项为代码生成的输出添加标签。在下面的学习中,你将看到如何为非代码生成的元素(如方程表格静态图表)添加标签。

要交叉引用章节,你的文档 YAML 头部还必须包含:

number-sections: true

你可以在章节标题后的花括号中添加标签,例如:

## 数据与方法 {#sec-data-methods}

然后你可以在文本中引用这个章节,例如:

数据和方法在 @sec-data-methods 中讨论。

这将渲染为:

数据和方法在第2节中讨论。

你可以在 Quarto 交叉引用 文档中阅读更多关于可以引用的对象类型,包括代码列表和数学定理,以及一些控制引用显示方式的选项。

方程

Quarto markdown 可以包含使用 LaTeX 符号指定的方程。使用单个美元符号($)来添加行内方程,或使用双美元符号($$)来添加显示方程。以下段落展示了这两种用法,位于 index.ipynb 中:

设 $x$ 表示一年内的喷发次数。那么,$x$ 可以用泊松分布来建模

$$
p(x) = \frac{e^{-\lambda} \lambda^{x}}{x !}
$$ {#eq-poisson}

其中 $\lambda$ 是每年的喷发率。利用 @eq-poisson,可以计算未来 $t$ 年内发生喷发的概率。

请注意,显示方程在关闭的 $$ 后添加了花括号中的标签。这使得可以在文本中使用 @eq-poisson 来引用它。

渲染后,显示为:

\(x\) 表示一年内的喷发次数。那么,\(x\) 可以用泊松分布来建模 \[ p(x) = \frac{e^{-\lambda} \lambda^{x}}{x !} \tag{1}\] 其中 \(\lambda\) 是每年的喷发率。利用 Equation 1,可以计算未来 \(t\) 年内发生喷发的概率。

表格

表格可以通过所谓的管道语法内联添加。例如,在 index.ipynb 中,地震表被指定为:

| 名称                 | 年份   |
| -------------------- | ------ |
| 当前                 | 2021   |
| 特内吉亚             | 1971   |
| 南布罗克             | 1949   |
| 埃尔查科             | 1712   |
| 圣安东尼奥火山       | 1677   |
| 圣马丁火山           | 1646   |
| 埃尔帕索附近的塔朱亚 | 1585   |
| 蒙塔尼亚克马达       | 1492   |

: 拉帕尔马近期历史喷发 {#tbl-history}

列由管道符号 (|) 分隔,第二行的破折号 (-) 将标题行与表格的其余部分分隔开。可以通过以 : 开头的行提供标题。在标题末尾的花括号内添加一个可用于交叉引用的标签。与图表一样,交叉引用的标签前缀 tbl- 是必需的,但后缀由您决定。

您可以在 Quarto 文档的 表格 页面了解更多关于 Quarto 中的表格信息,包括称为网格表格的替代语法。

静态图表

要包含来自文件的图片,Markdown 语法如下所示:

![标题](图片文件路径)

例如,要包含项目中 images/ 文件夹下的 la-palma-map.png 图片,并附上标题 “La Palma 地图”,你可以这样写:

![La Palma 地图](images/la-palma-map.png)
图片文件位置

虽然 images/ 是一个常见的惯例,但你不必将图片存储在名为 images/ 的文件夹中。你的图片可以放在手稿项目目录内的任何位置,只需确保你包含了相对于 index.ipynb 位置的完整路径。

index.ipynb 中的实际 Markdown 还包括一个额外的属性 #fig-map,它在图片路径后的花括号内,用于提供交叉引用的标签:

![La Palma 地图](images/la-palma-map.png){#fig-map}

你可能希望添加的另一个属性是 fig-alt,即为图片提供的替代文本。例如:

![La Palma 地图](images/la-palma-map.png){#fig-map fig-alt="加那利群岛的地图。第二西部的岛屿,La Palma,被突出显示。"}

你可以在 Quarto 文档的 Figures 页面上阅读更多关于在 Quarto 文档中包含图片的内容,包括如何调整图片大小和排列多个图片。

外部嵌入

在文章笔记本中直接包含计算的另一种方法是嵌入其他笔记本的输出。本手稿项目在 notebooks/ 文件夹中包含了笔记本 data-screening.ipynb

要嵌入笔记本的输出,可以使用 embed 短代码。Quarto 短代码是生成内容的特殊 Markdown 指令。embed 短代码在主文章文件中的使用如下:

index.ipynb
{{< embed notebooks/data-screening.ipynb#fig-spatial-plot >}}

双大括号 ({{) 和尖括号 (<) 表示这是一个短代码。embed 短代码需要一个指向笔记本单元格的路径。在本例中,它是 data-screening.ipynb 的文件路径,后跟 # 和一个单元格标识符。这里的单元格标识符是单元格标签,使用 Quarto 单元格选项 labeldata-screening.ipynb 笔记本的代码单元格中设置:

data-screening.ipynb
#| label: fig-spatial-plot
#| fig-cap: "2017年以来拉帕尔马的地震位置。"
#| fig-alt: "地震位置的散点图,绘制纬度与经度。"
from matplotlib import colormaps
cmap = colormaps['viridis_r']
ax = df.plot.scatter(x="Longitude", y="Latitude", 
                     s=40-df["Depth(km)"], c=df["Magnitude"], 
                     figsize=(12,10), grid="on", cmap=cmap)
colorbar = ax.collections[0].colorbar
colorbar.set_label("Magnitude")

plt.show()

就像任何图形一样,使用以 fig- 开头的标签可以在文本中进行交叉引用。其他选项,如图注 (fig-cap) 和替代文本 (fig-alt),也可以在源笔记本中设置。

在本手稿中,笔记本 data-screening.ipynb 是不可复现的:你无法重新生成所有输出,因为某些输入(例如数据)未包含在项目中。但是,你可以在不重新运行笔记本中的代码单元格的情况下更改 Quarto 单元格选项。如果你将图注编辑为:

#| fig-cap: "2017年以来拉帕尔马的地震。"

当你保存 data-screening.ipynb 时,你会发现预览更新,并且图注会反映在文章本身中。

下一步

你现在已经了解了使用Quarto撰写手稿的主要功能。你编辑了index.ipynb,添加了图表、笔记本或参考文献等资源,并预览了结果。

一旦你对所做的更改感到满意,你需要更新你的公开手稿网页。

前往发布,学习如何发布并与全世界分享你的手稿。