跳转至

Quarto 数据报告完全指南

为什么要学 Quarto

  1. 下一代 R Markdown,但不限于 R:Quarto 是 RStudio/Posit 推出的开源科学与技术出版系统,支持 Python、R、Julia、Observable JS 四种语言。无论你用哪种语言做数据分析,Quarto 都是最佳的报告工具。

  2. 一次编写,多种输出:同一份 .qmd 源文件可以渲染为 HTML 网页、PDF 文档、Word 文档、PowerPoint 幻灯片、EPUB 电子书、Revealjs 幻灯片、甚至整本书籍和网站。不需要为不同格式维护多份内容。

  3. 学术论文级排版:内置交叉引用、引用管理(BibTeX)、数学公式(LaTeX)、图表编号、目录生成、页眉页脚等学术出版功能。可以直接投稿到多数学术期刊。

  4. 交互式数据可视化:HTML 输出支持 Observable JS 交互组件、Plotly 交互图表、Shiny 集成、tabset 面板等。报告不再是静态 PDF,而是可探索的数据应用。

  5. VS Code 与 RStudio 原生支持:丰富的 IDE 支持——实时预览、代码补全、chunk 运行、大纲视图。Quarto VS Code 插件是官方维护的,体验一流。


核心概念详解

Quarto 是什么(白话解释)

想象你在写一份报告:有文字解释,有数据图表,有代码。传统方式是在 Word 里插入截图,代码和输出不关联。Quarto 让你在同一文件中: - 写 Markdown 格式的文字 - 嵌入代码块(Python/R/Julia) - 代码执行结果(图表、表格)自动嵌入文档

当你修改数据或代码时,整份报告自动更新。这就是"可重复研究"(Reproducible Research)的核心理念。

Quarto vs R Markdown vs Jupyter

特性QuartoR MarkdownJupyter Notebook
维护方Posit (RStudio)PositProject Jupyter
语言支持Python/R/Julia/OJSR为主(可用Python)单内核为主
文件格式.qmd (纯文本).Rmd (纯文本).ipynb (JSON)
版本控制友好(纯文本)友好不友好(JSON+输出)
输出格式HTML/PDF/Word/PPT/书等HTML/PDF/WordHTML/PDF
交叉引用原生支持需bookdown不支持
多语言混用同一文档多语言需要knitr引擎限单内核
编辑器VS Code/RStudio/任意RStudio为主Jupyter Lab
出版能力书籍/网站/博客需bookdown/blogdown有限
参数化报告原生支持原生支持需papermill
协作Git友好Git友好冲突多

文档结构

一个 Quarto 文件(.qmd)由三部分组成:

---
title: "YAML 头部(元数据)"
author: "张三"
date: today
format: html
---

这里是 Markdown 正文。

```{python}
# 这里是代码块
import pandas as pd
df = pd.read_csv("data.csv")
df.head()

继续写正文...

### 输出格式概览

| 格式 | YAML 配置 | 用途 |
|------|----------|------|
| HTML 单页 | `format: html` | 交互式报告、分享 |
| PDF | `format: pdf` | 打印、正式文档 |
| Word | `format: docx` | 与非技术人员协作 |
| PowerPoint | `format: pptx` | 幻灯片 |
| Revealjs | `format: revealjs` | 网页幻灯片 |
| 书籍 | Quarto Book 项目 | 教材、技术书 |
| 网站 | Quarto Website 项目 | 文档站、博客 |
| Dashboard | `format: dashboard` | 数据仪表板 |

---

## 安装与配置

### 安装 Quarto CLI

```bash
# macOS (Homebrew)
brew install quarto

# Linux (Ubuntu/Debian)
wget https://github.com/quarto-dev/quarto-cli/releases/download/v1.6.40/quarto-1.6.40-linux-amd64.deb
sudo dpkg -i quarto-1.6.40-linux-amd64.deb

# Windows (Chocolatey)
choco install quarto

# 或直接从官网下载安装包
# https://quarto.org/docs/get-started/

# 验证安装
quarto --version
quarto check

配置 Python 环境

# 安装 Jupyter(Quarto 用它执行 Python 代码)
pip install jupyter jupyterlab

# 常用数据科学包
pip install pandas numpy matplotlib seaborn plotly scikit-learn

# 验证
quarto check jupyter

配置 R 环境

# 在 R 中安装
install.packages(c("rmarkdown", "knitr", "tidyverse", "ggplot2"))

VS Code 配置

# 安装 Quarto 插件
code --install-extension quarto.quarto

VS Code 设置(settings.json):

{
  "quarto.mathjax": true,
  "quarto.render.previewType": "internal"
}

项目初始化

# 创建新项目
quarto create project default my-report
quarto create project website my-blog
quarto create project book my-book

# 项目结构
my-report/
├── _quarto.yml        # 项目配置
├── index.qmd          # 主文件
├── styles.css         # 自定义样式
└── references.bib     # 参考文献

_quarto.yml 配置

project:
  type: website
  output-dir: _site

website:
  title: "数据分析报告"
  navbar:
    left:
      - href: index.qmd
        text: 首页
      - href: analysis.qmd
        text: 分析
      - href: about.qmd
        text: 关于

format:
  html:
    theme: cosmo
    css: styles.css
    toc: true
    toc-depth: 3
    code-fold: true
    code-tools: true

快速上手:5 分钟最小示例

创建 report.qmd

---
title: "销售数据分析"
author: "数据团队"
date: today
format:
  html:
    toc: true
    code-fold: true
    theme: flatly
execute:
  echo: true
  warning: false
---

## 概述

本报告分析了 2024 年的销售数据趋势。

## 数据加载

```{python}
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 模拟销售数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=365, freq='D')
sales = 1000 + np.cumsum(np.random.randn(365) * 50)

df = pd.DataFrame({'date': dates, 'sales': sales})
df['month'] = df['date'].dt.month
df['weekday'] = df['date'].dt.day_name()

print(f"数据范围: {df['date'].min()} 到 {df['date'].max()}")
print(f"平均日销售额: ¥{df['sales'].mean():.0f}")

月度趋势

#| label: fig-monthly
#| fig-cap: "2024年月度销售趋势"

monthly = df.groupby('month')['sales'].mean().reset_index()

plt.figure(figsize=(10, 5))
plt.bar(monthly['month'], monthly['sales'], color='steelblue')
plt.xlabel('月份')
plt.ylabel('平均日销售额 (¥)')
plt.title('2024年各月平均日销售额')
plt.xticks(range(1, 13))
plt.tight_layout()
plt.show()

如 @fig-monthly 所示,销售额在年中达到高峰。

统计摘要

#| label: tbl-summary
#| tbl-cap: "按月统计摘要"

summary = df.groupby('month')['sales'].agg(['mean', 'std', 'min', 'max']).round(0)
summary.columns = ['平均', '标准差', '最低', '最高']
summary.index.name = '月份'
summary

结论

根据 @tbl-summary 的数据,我们可以看到...

渲染报告:
```bash
quarto render report.qmd
# 输出: report.html

# 实时预览(修改自动刷新)
quarto preview report.qmd


进阶用法

场景一:交叉引用系统

---
title: "完整论文示例"
format:
  html:
    number-sections: true
  pdf:
    number-sections: true
crossref:
  fig-prefix: "图"
  tbl-prefix: "表"
  eq-prefix: "公式"
---

## 方法 {#sec-methods}

本研究采用的方法如 @sec-methods 所述。

### 数学模型

损失函数定义如 @eq-loss:

$$
L(\theta) = -\frac{1}{N}\sum_{i=1}^{N} y_i \log(\hat{y}_i)
$$ {#eq-loss}

### 实验结果

```{python}
#| label: fig-results
#| fig-cap: "实验结果对比"
#| fig-subcap:
#|   - "训练损失"
#|   - "验证准确率"
#| layout-ncol: 2

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
ax.plot(np.exp(-np.linspace(0, 3, 100)))
ax.set_title("Training Loss")
plt.show()

fig, ax = plt.subplots()
ax.plot(1 - np.exp(-np.linspace(0, 2, 100)))
ax.set_title("Validation Accuracy")
plt.show()

如 @fig-results 所示,模型在训练过程中收敛良好。

### 场景二:参数化报告

```markdown
---
title: "{{< meta params.region >}} 区域销售报告"
params:
  region: "华东"
  year: 2024
  threshold: 1000
format: html
---

```{python}
region = "{{< meta params.region >}}"
year = {{< meta params.year >}}
threshold = {{< meta params.threshold >}}

# 根据参数过滤数据
filtered_data = df[(df['region'] == region) & (df['year'] == year)]
print(f"分析区域: {region}, 年份: {year}")
print(f"阈值: {threshold}")
批量生成:
```bash
# 为不同区域生成报告
quarto render report.qmd -P region:"华东" -P year:2024
quarto render report.qmd -P region:"华南" -P year:2024
quarto render report.qmd -P region:"华北" -P year:2024

场景三:多语言混用

---
title: "多语言数据分析"
format: html
---

## Python 数据处理

```{python}
import pandas as pd
data = pd.DataFrame({'x': range(10), 'y': [i**2 for i in range(10)]})
data.to_csv('/tmp/shared_data.csv', index=False)
print("Python 处理完成")

R 可视化

library(ggplot2)
data <- read.csv('/tmp/shared_data.csv')
ggplot(data, aes(x=x, y=y)) +
  geom_point() +
  geom_smooth() +
  theme_minimal() +
  labs(title="R 绘制的图表")

Observable JS 交互

data = FileAttachment("data.csv").csv({typed: true})

viewof threshold = Inputs.range([0, 100], {label: "阈值", step: 1, value: 50})

Plot.plot({
  marks: [
    Plot.dot(data.filter(d => d.y > threshold), {x: "x", y: "y"})
  ]
})
### 场景四:Dashboard(仪表板)

```markdown
---
title: "销售仪表板"
format: dashboard
---

## Row {height=30%}

### 总销售额

```{python}
#| content: valuebox
#| title: "总销售额"
dict(value="¥12.5M", icon="currency-yen", color="primary")

订单数

#| content: valuebox
#| title: "总订单数"
dict(value="8,234", icon="cart", color="success")

客户数

#| content: valuebox
#| title: "活跃客户"
dict(value="1,567", icon="people", color="info")

Row

销售趋势

import plotly.express as px
import pandas as pd
import numpy as np

dates = pd.date_range('2024-01-01', periods=90, freq='D')
sales = np.cumsum(np.random.randn(90) * 100) + 5000

fig = px.line(x=dates, y=sales, title="日销售额趋势")
fig.update_layout(xaxis_title="日期", yaxis_title="销售额 (¥)")
fig.show()

品类分布

categories = ['电子产品', '服装', '食品', '家居', '运动']
values = [35, 25, 20, 12, 8]

fig = px.pie(names=categories, values=values, title="销售品类占比")
fig.show()
### 场景五:学术论文(PDF + 引用管理)

```markdown
---
title: "深度学习在自然语言处理中的应用"
author:
  - name: "张三"
    affiliation: "清华大学计算机系"
    email: zhang@example.com
  - name: "李四"
    affiliation: "北京大学信息学院"
date: 2024-12-01
abstract: |
  本文综述了深度学习在NLP领域的最新进展...
bibliography: references.bib
csl: ieee.csl
format:
  pdf:
    documentclass: article
    papersize: a4
    fontsize: 11pt
    geometry:
      - margin=2.5cm
    number-sections: true
    cite-method: biblatex
---

## 引言

自从 Transformer 架构被提出 [@vaswani2017attention] 以来,
自然语言处理取得了巨大进展。BERT [@devlin2019bert] 和
GPT [@brown2020language] 系列模型...

## 方法

### 模型架构

我们采用了改进的注意力机制,如 @eq-attention 所示:

$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$ {#eq-attention}

## 参考文献

::: {#refs}
:::

references.bib

@article{vaswani2017attention,
  title={Attention is all you need},
  author={Vaswani, Ashish and others},
  journal={NeurIPS},
  year={2017}
}

场景六:Revealjs 幻灯片

---
title: "数据驱动决策"
subtitle: "Q4 业务回顾"
author: "数据分析部"
date: 2024-12-15
format:
  revealjs:
    theme: dark
    slide-number: true
    transition: slide
    chalkboard: true
    code-fold: true
---

## 第一部分 {background-color="#1a1a2e"}

### 业务概览

- 季度收入增长 **23%**
- 新客户获取成本降低 **15%**
- 用户留存率提升至 **87%**

::: {.notes}
演讲者备注:强调增长趋势
:::

---

### 关键指标

```{python}
#| output-location: slide
import plotly.express as px
# 图表代码...
fig.show()

下季度计划

::: {.columns} ::: {.column width="50%"} 技术目标

  • 系统性能优化
  • 新功能上线 ::: ::: {.column width="50%"} 业务目标

  • 扩展新市场

  • 提升客户满意度 ::: :::
    ---
    
    ## 常见问题与排错
    
    ### 问题一:Python 代码块不执行
    
    **原因**:Quarto 找不到 Jupyter 内核。
    
    ```bash
    # 检查 Jupyter 是否可用
    quarto check jupyter
    
    # 确保 jupyter 在 PATH 中
    which jupyter
    
    # 指定 Python 路径
    # 在 _quarto.yml 或文件头部添加:
    # jupyter: python3
    

问题二:PDF 渲染失败

原因:缺少 LaTeX 环境。

# 安装 TinyTeX(Quarto 推荐的轻量 LaTeX)
quarto install tinytex

# 或安装缺少的包
tlmgr install <package-name>

问题三:中文 PDF 乱码

format:
  pdf:
    pdf-engine: xelatex
    CJKmainfont: "Source Han Serif CN"
    mainfont: "Source Han Sans CN"

问题四:图表不显示

# Matplotlib 需要 plt.show() 或在设置中启用
#| fig-show: "asis"

import matplotlib
matplotlib.use('Agg')  # 非交互模式
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.show()

问题五:代码块选项解释

#| label: fig-example      # 用于交叉引用
#| fig-cap: "图表标题"     # 图表说明
#| fig-width: 8            # 图表宽度(英寸)
#| fig-height: 5           # 图表高度
#| echo: false             # 不显示代码
#| eval: true              # 是否执行
#| output: true            # 是否显示输出
#| warning: false          # 隐藏警告
#| code-fold: true         # 折叠代码

问题六:渲染速度慢

execute:
  freeze: auto  # 代码没变就不重新执行
  cache: true   # 缓存执行结果
# 只渲染特定文件
quarto render specific-file.qmd

# 并行渲染
quarto render --execute-daemon

参考资源

  • 官方网站:https://quarto.org
  • 入门教程:https://quarto.org/docs/get-started/
  • 完整指南:https://quarto.org/docs/guide/
  • Gallery(示例展示):https://quarto.org/docs/gallery/
  • GitHub:https://github.com/quarto-dev/quarto-cli
  • VS Code 插件:https://marketplace.visualstudio.com/items?itemName=quarto.quarto
  • Awesome Quarto:https://github.com/mcanouil/awesome-quarto
  • Quarto 中文论坛:https://d.cosx.org/(统计之都)