Quarto 数据报告完全指南¶
为什么要学 Quarto¶
下一代 R Markdown,但不限于 R:Quarto 是 RStudio/Posit 推出的开源科学与技术出版系统,支持 Python、R、Julia、Observable JS 四种语言。无论你用哪种语言做数据分析,Quarto 都是最佳的报告工具。
一次编写,多种输出:同一份
.qmd源文件可以渲染为 HTML 网页、PDF 文档、Word 文档、PowerPoint 幻灯片、EPUB 电子书、Revealjs 幻灯片、甚至整本书籍和网站。不需要为不同格式维护多份内容。学术论文级排版:内置交叉引用、引用管理(BibTeX)、数学公式(LaTeX)、图表编号、目录生成、页眉页脚等学术出版功能。可以直接投稿到多数学术期刊。
交互式数据可视化:HTML 输出支持 Observable JS 交互组件、Plotly 交互图表、Shiny 集成、tabset 面板等。报告不再是静态 PDF,而是可探索的数据应用。
VS Code 与 RStudio 原生支持:丰富的 IDE 支持——实时预览、代码补全、chunk 运行、大纲视图。Quarto VS Code 插件是官方维护的,体验一流。
核心概念详解¶
Quarto 是什么(白话解释)¶
想象你在写一份报告:有文字解释,有数据图表,有代码。传统方式是在 Word 里插入截图,代码和输出不关联。Quarto 让你在同一文件中: - 写 Markdown 格式的文字 - 嵌入代码块(Python/R/Julia) - 代码执行结果(图表、表格)自动嵌入文档
当你修改数据或代码时,整份报告自动更新。这就是"可重复研究"(Reproducible Research)的核心理念。
Quarto vs R Markdown vs Jupyter¶
| 特性 | Quarto | R Markdown | Jupyter Notebook |
|---|---|---|---|
| 维护方 | Posit (RStudio) | Posit | Project Jupyter |
| 语言支持 | Python/R/Julia/OJS | R为主(可用Python) | 单内核为主 |
| 文件格式 | .qmd (纯文本) | .Rmd (纯文本) | .ipynb (JSON) |
| 版本控制 | 友好(纯文本) | 友好 | 不友好(JSON+输出) |
| 输出格式 | HTML/PDF/Word/PPT/书等 | HTML/PDF/Word | HTML/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 环境¶
VS Code 配置¶
VS Code 设置(settings.json):
项目初始化¶
# 创建新项目
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 的数据,我们可以看到...
进阶用法¶
场景一:交叉引用系统¶
---
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")
订单数¶
客户数¶
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%"} 业务目标
扩展新市场
- 提升客户满意度 ::: :::
问题二:PDF 渲染失败¶
原因:缺少 LaTeX 环境。
问题三:中文 PDF 乱码¶
问题四:图表不显示¶
# 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 # 折叠代码
问题六:渲染速度慢¶
参考资源¶
- 官方网站: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/(统计之都)