Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Activity 4.2

This page is an ipython notebook, meaning you can download it and run the executable cells. It directly follows Activity 4.2. Reference answers appear after the questions, challenges, predictions, and reflections. They show one reasonable solution or interpretation, but other correct approaches may exist.

Reproducibility & Reporting with Jupyter and Quarto

Tools: Python, Jupyter, Quarto, pandas, matplotlib, Git

Learning objectives

By the end of this tutorial, you should be able to:

  • evaluate whether a notebook is reproducible;

  • eliminate hidden execution-state dependencies;

  • create a computational report;

  • combine Markdown, Python, tables, and figures;

  • render a Quarto document;

  • generate HTML and other outputs from one source;

  • dynamically compute reported quantities;

  • import reusable functions from src/;

  • record Python dependencies;

  • control randomness;

  • separate raw, processed, and report outputs;

  • perform a final reproducibility test.


Part 0 — Project setup

Extend your existing STA 556 project:

project/
├── README.md
├── data/
│   ├── raw/
│   └── processed/
├── notebooks/
├── src/
├── figures/
├── reports/
└── tests/

Create:

reports/week08_report.qmd

Also create:

notebooks/week08_reproducibility.ipynb

Create a small Quarto project configuration at the repository root:

_quarto.yml

with:

project:
  type: default
  execute-dir: project

execute-dir: project tells Quarto to execute report code from the project root. This keeps paths such as data/processed/week08_data.csv and imports such as from src... consistent with the rest of the course.


Part 1 — Verify the provided computational environment

From the terminal:

python --version

Check:

quarto --version

If quarto --version fails in the official course Codespace, treat that as a course-environment issue rather than installing Quarto manually.

Then:

python -m pip show pandas

and:

python -m pip show matplotlib

Reflection

Why could package versions matter if the same source code is run several years later?


Part 2 — Create a deliberately fragile notebook

In:

notebooks/week08_reproducibility.ipynb

create cells in this order.

Cell 1

Cell 2

Cell 3

Cell 4

Now execute:

Cell 1
Cell 3
Cell 4
Cell 2

The notebook appears to work.


Reference answer

Package versions matter because APIs, defaults, numerical behavior, and rendering can change over time. Recording dependencies helps recreate the original environment.

Part 3 — Restart and run all

Restart the kernel.

Then run all cells from top to bottom.

Question

What fails?

Why?

Fix the notebook by moving computations before anything that depends on them.

Repeat:

Restart kernel
Run all

until the notebook succeeds.


Reference answer

Restart-and-run-all exposes hidden notebook state. If a variable only exists because cells were executed out of order, a clean top-to-bottom run will fail and reveal the dependency.

Part 4 — Add a reproducible random generator

Compare:

with:

Restart the kernel and rerun.

Question

Which one reproduces the same values?

Why will this matter during future simulation modules?

Reference answer

Using an explicit random generator and seed makes stochastic output reproducible while keeping randomness visible as part of the analysis.


Part 5 — Build a small processed dataset

Create:

Then:

Save:


Reference answer

Saving a processed dataset creates a reproducible boundary between preparation and reporting; the report can consume the same well-defined input each time.

Part 6 — Create a reusable summary function

In:

src/week08_analysis.py

write:

Then:

Save.

Reference answer

A reusable summary function prevents copied logic from drifting across reports. Fixes and changes can be made once.


Part 7 — Use your module

In the notebook:

Then:

Reflection

Why is this preferable to copying the summary logic into every report?


Part 8 — Create a basic Quarto document

Open:

reports/week08_report.qmd

Add:

---
title: "STA 556 Week 8 Reproducible Report"
author: "Your Name"
format: html
jupyter: python3
---

Then:

# Introduction

This report demonstrates a reproducible statistical
workflow using Python and Quarto.

Reference answer

A document that combines narrative with executable code keeps analysis and interpretation synchronized and easier to regenerate.

Part 9 — Add setup code

Add a Python block:

`

{python} import pandas as pd import matplotlib.pyplot as plt

from src.week08_analysis import summarize_groups

`

Depending on where your report is located, you may need to ensure the project root is the working directory.

Question

Why should path assumptions be explicit?


Part 10 — Load the data

Add:

`

{python} df = pd.read_csv( “data/processed/week08_data.csv” )

df.head()

`

Important

Do not manually recreate the DataFrame inside the report.

The report should consume the processed analytical data.

Reference answer

Project-relative paths are preferable to machine-specific absolute paths because the project can be cloned or moved without editing file locations.


Part 11 — Add a data-validation block

Add:

`

{python} assert len(df) == 100 assert df[“id”].is_unique assert df[“score”].notna().all()

`

Question

Why include checks in a report-generation workflow?

What happens if the upstream data unexpectedly change?


Part 12 — Generate a summary table

Add:

`

{python} summary = summarize_groups(df) summary

`

Add narrative:

## Descriptive statistics

The table below summarizes assessment scores by group.

Reflection

If the data change, what must you manually update?

Ideally: nothing.

Reference answer

Generating summary tables from code ensures displayed values correspond to the current data rather than manually copied numbers.


Part 13 — Generate a dynamic value

Calculate:

Use the result in your narrative.

If your chosen Quarto/Jupyter workflow supports inline execution, insert it dynamically.

If not, generate a compact results object in a code block and reference the reported value immediately below it.

Principle

Do not manually copy a statistic if the document can generate it.

Reference answer

If the data change, ideally nothing is manually updated; rerendering should recompute dynamic values automatically.


Part 14 — Create a figure in the report

Add:

`

{python} fig, ax = plt.subplots( figsize=(7, 5) )

ax.hist( df[“score”], bins=15 )

ax.set( title=“Distribution of assessment scores”, xlabel=“Assessment score”, ylabel=“Frequency” )

plt.show()

`

Render later and verify the figure appears.


Part 15 — Add a figure caption

Use Quarto cell options:

`

{python} #| label: fig-score-distribution #| fig-cap: “Distribution of assessment scores.”

fig, ax = plt.subplots()

ax.hist( df[“score”], bins=15 )

ax.set( xlabel=“Assessment score”, ylabel=“Frequency” )

plt.show()

`

Now reference the figure in your prose according to Quarto’s cross-reference syntax.


Part 16 — Render the report

From the project root:

quarto render reports/week08_report.qmd

Locate the resulting HTML file.

Open it.

Questions

  1. Did the Python code execute?

  2. Did the table appear?

  3. Did the figure appear?

  4. Did the narrative render correctly?


Part 17 — Preview during development

Run:

quarto preview reports/week08_report.qmd

In GitHub Codespaces, Quarto runs the preview server inside the Codespace, not on your laptop. Codespaces detects the preview server and exposes it through a forwarded port. Use the Open in Browser notification or the VS Code Ports panel rather than manually typing a localhost address.

Edit the report and observe the preview update.

Reflection

When is preview useful?

When would you use render instead?

Reference answer

Previewing is useful during development, but the final artifact should still be reproducible from a clean execution.


Part 18 — Control code visibility

At the top of the document, experiment with:

execute:
  echo: false

Render.

What changed?

Now remove it and instead hide only one code block:

`

{python} #| echo: false

summary

`

Question

Why might a report hide code from one audience but show it to another?

Reference answer

Hiding code may improve reader-facing presentation, but the source should preserve the executable analysis needed for reproducibility.


Part 19 — Code folding

For HTML, experiment with:

format:
  html:
    code-fold: true

Render.

Reflection

How does code folding balance readability and transparency?

Reference answer

Code folding lets readers focus on interpretation while still allowing inspection of implementation details.


Part 20 — Generate a Word version

Change:

format:
  html: default
  docx: default

Then:

quarto render reports/week08_report.qmd

Inspect both outputs.

Question

What benefit comes from generating both from one source?

Reference answer

Rendering multiple formats from one source reduces copy/paste divergence because the analysis logic remains the same.


Part 21 — Optional PDF output

If your environment has the required PDF tooling, add:

pdf: default

and render.

If PDF rendering fails because a TeX dependency is missing, document the dependency rather than treating it as an analysis error.

Reference answer

PDF is useful when fixed layout matters, though it may require extra rendering dependencies; the underlying analysis should remain unchanged.


Part 22 — Add meaningful labels

Review all figures and tables.

Replace:

score
age
group

with reader-friendly labels where appropriate:

Assessment score
Age (years)
Study group

Principle

The report is for a reader, not for the DataFrame.


Part 23 — Build a proper report structure

Organize:

# Introduction

# Data

# Methods

# Results

## Descriptive statistics

## Visualization

# Discussion

Challenge

Write 1–3 sentences for each section.

Keep the report concise.


Part 24 — Separate computation from interpretation

Example:

## Results

[computed table]

Group A had a higher mean score than Group B.

The table is computational output.

The sentence is statistical interpretation.

Question

Why should these remain conceptually distinct?

Reference answer

Keep computation in executable code and interpretation in prose. Numerical results should be generated, not manually typed, whenever possible.


Part 25 — Make the report fail deliberately

Rename:

data/processed/week08_data.csv

temporarily.

Render the report.

Question

What happens?

Why is an obvious failure preferable to silently using old manually copied results?

Restore the file afterward.

Reference answer

A deliberate failure checks that the report truly depends on documented inputs/environment rather than stale state.


Part 26 — Record the environment

From the terminal:

python -m pip freeze > requirements.txt

Open:

requirements.txt

Inspect several entries.

Question

What does this file record?

What does it not record?

Reference answer

Record package/runtime versions so another analyst can reconstruct the software context.


Part 27 — Reproducibility test in a fresh environment

Conceptually, another user should be able to run:

python -m pip install -r requirements.txt

This command documents how an environment can be recreated, but students normally do not need to run it in STA 556 Codespaces because the course dependencies are installed automatically when the Codespace is created. Treat requirements.txt as part of the reproducibility record rather than as a weekly installation step.

and then:

quarto render reports/week08_report.qmd

You do not need to destroy your current environment.

Instead, explain the steps another researcher would follow.

Reference answer

A fresh-environment test removes hidden local assumptions and is strong evidence that the workflow is reproducible.


Part 28 — Make a clean execution test

Before the final render:

  1. restart the Jupyter kernel;

  2. run the notebook from beginning to end;

  3. save it;

  4. render the Quarto report;

  5. inspect warnings/errors;

  6. verify the reported numbers.

Question

Why is this stronger than simply checking whether the final HTML file exists?

Reference answer

A clean execution test asks whether the artifact can be rebuilt from documented inputs, in order, without prior interactive state.


Part 29 — Remove manual values

Search your report for manually typed statistical quantities.

For example:

The mean score was 81.37.

Ask:

Could this value be generated computationally?

If yes, replace the manual workflow.


Part 30 — One-source-many-outputs challenge

Configure the report to produce at least:

HTML
DOCX

from the same .qmd.

Render both.

Compare:

  • tables;

  • figures;

  • headings;

  • code;

  • overall readability.

Reflection

What formatting differences exist despite sharing one source?

Reference answer

One-source-many-outputs prevents copy/edit drift: the same source can generate multiple formats while keeping calculations synchronized.


Part 31 — Parameterized-report concept

Imagine you need one report per group.

Instead of:

report_A.qmd
report_B.qmd

think:

report.qmd
+
group parameter

Sketch how your functions would need to work:

Question

What advantages does this have over copying and editing reports?

Reference answer

Parameterized reports reuse one template while varying an explicit parameter, reducing duplication and making repeated reporting systematic.


Part 32 — Automation concept

Create a small shell script conceptually containing:

python src/prepare_data.py
quarto render reports/week08_report.qmd

You do not need sophisticated automation yet.

The point is to see the report as the final step of a computational pipeline.

Reference answer

Automation reduces repetitive manual steps and the risk of forgetting to regenerate part of a workflow.


Part 33 — Cache discussion

Suppose your analysis takes two hours.

Would you want Quarto to recompute it every time you change one sentence?

Discuss:

  • benefits of caching;

  • risk of stale computation;

  • when recomputation is preferable.

Reference answer

Caching can save time for expensive computations but can also preserve stale results if dependencies are not tracked correctly.


Part 34 — Audit the report

Use this checklist.

Data

  • Is the data source clear?

  • Is the processed file generated reproducibly?

  • Are raw data preserved?

Code

  • Are transformations in code?

  • Are reusable functions in src/?

  • Are assumptions checked?

Environment

  • Is requirements.txt present?

Randomness

  • Are seeds controlled?

Report

  • Are statistics generated dynamically?

  • Are figures generated from code?

  • Are tables generated from code?

  • Can the report render from beginning to end?


Part 35 — Peer reproducibility test

If possible, exchange repositories with a classmate.

Without verbal instructions, attempt to determine:

  1. Which file is the report source?

  2. Which data file does it use?

  3. Which Python module does it import?

  4. How should the report be rendered?

  5. What dependencies are required?

Important

If your partner must ask you where everything is, improve the project documentation.


Part 36 — Update the README

Add:

## Week 8 report

To render the report:

bash quarto render reports/week08_report.qmd


Required Python dependencies are listed in:

text requirements.txt

Also document where input data are located.


Part 37 — Git checkpoint

Run:

git status

Review carefully.

Do you want to commit:

.qmd source?
requirements.txt?
src module?
processed data?
rendered HTML?
rendered Word document?

Your choice should be deliberate.

Then:

git add .
git commit -m "Complete Week 8 reproducible reporting workflow"
git push

Part 38 — Final reflection

Answer in Markdown.

1. Reproducibility

What information is required to reproduce a computational analysis?

2. Jupyter

What is hidden state, and why can it be dangerous?

3. Literate programming

What does it mean to combine narrative and computation?

4. Quarto

What role does Quarto play in the workflow?

5. Dynamic reporting

Why are dynamically generated statistics preferable to manually copied values?

6. Environments

Why should package dependencies be recorded?

7. Randomness

Why should random seeds be explicit?

8. Rendered outputs

Why should rendered Word/HTML/PDF files usually not become the primary source document?

9. Modularity

How did the Week 7 function/module work improve this week’s report?

10. Scientific validity

Why can a workflow be reproducible but still statistically wrong?


Completion checklist

  • Created Week 8 notebook

  • Created a Quarto .qmd report

  • Demonstrated hidden notebook state

  • Restarted and ran a notebook from top to bottom

  • Controlled randomness with a generator/seed

  • Created processed data

  • Created a reusable analysis module

  • Imported module functions into the workflow

  • Added Quarto YAML metadata

  • Loaded data from the report

  • Added validation checks

  • Generated a dynamic summary table

  • Generated a figure from code

  • Added a figure caption

  • Rendered an HTML report

  • Used quarto preview

  • Controlled code visibility

  • Experimented with code folding

  • Generated a Word report

  • Explored PDF rendering if available

  • Added reader-friendly labels

  • Structured the report into narrative sections

  • Deliberately triggered a reproducibility failure

  • Created requirements.txt

  • Documented how to restore dependencies

  • Performed a clean execution test

  • Removed manually copied statistical values

  • Produced multiple output formats from one source

  • Explored parameterized-report design

  • Explored automated rendering

  • Audited the project for reproducibility

  • Attempted a peer reproducibility test

  • Updated the README

  • Committed Week 8 work to Git

  • Pushed work to GitHub


What you should now understand

Raw data
   ↓
Documented environment
   ↓
Modular code
   ↓
Computational document
   ↓
Execute from beginning to end
   ↓
Generate tables + figures + values
   ↓
Render
   ↓
HTML / Word / PDF
   ↓
Another person can reproduce it

Next week we move into Matrix Computation & Linear Algebra, including broadcasting, vectorized operations, SVD, and QR decomposition for statistical computing.

Reference answer

A reproducible workflow records dependencies, uses project-relative paths, controls randomness, separates reusable code from reporting, avoids manually copied results, and rebuilds cleanly from source.