Session 3: Reproducible Reports with Quarto
Monday, 28 September 2026, 09:00–11:15 · Room MAD 099
Pricing the Barcelona hotel market — individual, pass/fail, and required for exam admission. Due Sunday 18 October, 23:59. The task sheet and the data go up on Moodle today; summary at the bottom of this page.
What this session is about
You have the answer already: among four-star hotels in Vienna, the central ones charge about €43 more per night. Today the board wants it as a document — two pages they can read in a meeting and forward to a colleague.
The obvious way to produce that document is to paste the table into Word and type the number into the first paragraph. That works until somebody changes the data, at which point the text and the table quietly start disagreeing with each other and nobody notices until the meeting.
Today is about the alternative: a document that computes its own numbers every time it is built, so it cannot contradict itself. Along the way: the YAML header, Markdown, chunk options, why the render is not your console, figures and tables you can refer to by name, citations — and the error messages you will meet while getting there.
One new one, here — see New this session: i_am() and here() below for what it does:
install.packages("here")Plus tidyverse and flextable from sessions 1 and 2. The optional messy-import task in the take-home also uses janitor, which you can install when you get there.
Your session 1 and session 2 files were Quarto documents. Today we stop treating Quarto as the thing that happens to be around the code, and use it properly.
Learning goals
- Create a Quarto document, and read a YAML header well enough to write one
- Format prose in Markdown — headings, emphasis, lists, links
- Control what each chunk shows with
echo,eval,includeandlabel - Explain why the render is not your console, and why
View(),install.packages()andsetwd()therefore do not belong in a chunk - Use
i_am()andhere()for file paths that survive leaving your laptop, and say what a relative path is actually relative to - Put computed values into prose with inline R code — and never type a number into a sentence again
- Give figures and tables labels and captions, and cross-reference them
- Cite sources from a
.bibfile, including the dataset - Name the formats a
.qmdcan produce, and know which one this course wants - Read the four error messages that account for most failed renders
Slides
Open the slides in a separate tab
Open the slides in a separate tab in Chrome, add ?print-pdf to the end of the address, then print to PDF.
Materials
| File | Description |
|---|---|
| Exercise sheet | The in-session exercise |
| hotels-vienna.csv | The data, as in sessions 1 and 2 |
| hotels-vienna-messy.csv | The same data, badly exported — for the optional task |
| Slides | The deck from the session |
| Live coding document | The narrated code we wrote together |
| Exemplary solution | Worked answers to the exercise |
Data
The same Vienna hotels dataset as sessions 1 and 2 — the third and last session on it. Today the analysis is deliberately one you have already done, so that your attention goes on the document rather than on the question.
Békés and Kézdi (2021), licensed CC BY-NC-SA 4.0. Unmodified.
hotels-vienna-messy.csv
This one is modified. It carries the nine columns the analysis actually uses, re-exported the way a German Excel would export them: semicolons between fields, decimal commas, umlauts in ISO-8859-1 rather than UTF-8, column headers with spaces and brackets, and k.A. written where a guest rating is missing.
No value was changed — every one of those nine columns round-trips back to the original, which is what the optional task asks you to demonstrate. Adapted from Békés and Kézdi (2021) and shared under the same CC BY-NC-SA 4.0 licence.
New this session: i_am() and here()
Until now an RStudio project plus a relative path has been enough. From today, paths go through the here package — and every document starts by saying where it is:
library(here)
i_am("session03.qmd") # where this document sits in the project
hotels <- read_csv(here("data", "hotels-vienna.csv"))here() builds paths from the top of your project, so the same line works on your laptop, on mine, and on a marker’s. i_am() tells it where that top is instead of letting it search — which is the difference between a path that is checked and one that merely has not failed yet.
Install the package once if you have not already:
install.packages("here")here::i_am() above, here() in every path. All semester, and Report 1 asks for both. Two lines, and file paths stop being a source of failure.
here() cannot find your data
The problem is almost never here(). It is that you opened the .qmd file directly instead of opening the project. Close everything, open applied-data-science.Rproj, and try again.
With here::i_am() in place you get told this immediately, by name, instead of discovering it at whichever read_csv() happens to run first.
The question we answer
Not a new one about hotels — a new one about documents:
How do you write an analysis down so that it still gives the right answer after somebody changes the data?
Two places, both uncomfortable.
The first: every number in a report should be computed, not typed. That sounds like a style preference until you change one filter and watch six numbers move at once — four of which you would have missed by hand.
The second is worse. We defined “central” as within one kilometre and got a premium of about €43. Split that first kilometre in half and the step between the two innermost bands is about €21. Nobody made a mistake; they are different questions. A reader given only the number cannot tell that a boundary was ever chosen. A reader given the document with its code can move it themselves.
That is the actual argument for reproducibility, and it is why all three reports are submitted as source plus output.
Take-home until session 4
- Report 1 — start it this week, not in the third week
- Read Wickham et al. (2023), ch. 28 “Quarto” — about 40 minutes, and it covers everything on the exercise checklist
- Optional but genuinely useful: the messy import task on the exercise sheet. Real data arrives in that state more often than not.
- Also optional, and worth starting in the background: the PDF task at the end of the exercise sheet. HTML is all this course requires, but the LaTeX installation is easier to run one evening than in a seminar room.
- If anything from the first three sessions felt shaky, this is the time
There is no session on 5 October and 12 October. Report 1 will not take both weeks. If the R or the statistics has been uncomfortable so far, work through First steps in R (Gräbner-Radkowitsch 2026a) or the statistics recap track (Gräbner-Radkowitsch 2026b) now. From session 5 the course stops revisiting the basics.
Session 4 is Git and GitHub — version control, entirely through the RStudio interface, with no command line.
Report 1
| Task | Pricing the Barcelona hotel market |
| Task sheet | on Moodle, with the data and a separate hints document, from today |
| Issued | end of this session, 28 September |
| Due | Sunday 18 October, 23:59 |
| Form | individual, pass/fail — required for exam admission |
| Submit | via Moodle: the rendered report and a zip of your project folder |
| Debrief | session 4 |
Same structure as today’s exercise, on a city you have not seen: do the Vienna prices tell you anything about what a hotel in central Barcelona could charge? The full task description, the data and the assessment criteria are on Moodle. The Reports page here carries the deadlines and the rules that apply to all three.
Because a rendered HTML file is a claim, and the project is the evidence. Your report has to reproduce: I unzip your folder, open the .Rproj, restart R, render — and it has to give me your document, on my machine, without edits.
That is not an administrative hurdle. It is the one thing today’s session is about, and it is the difference between an analysis somebody can check and one they have to believe.
You can guarantee this half yourself in two minutes: unzip your own submission into an empty folder somewhere else and render it from there.
Going further
- Wickham et al. (2023), ch. 28 “Quarto” — the same ground, more slowly
- Quarto: Get Started and the HTML / PDF format guides
- Quarto: Cross-references
- Quarto: Citations
- The
herepackage — short, and the “why” section is worth reading
Before you submit anything in this course, it should:
- render to HTML, from a restarted R session
- contain no typed numbers in the prose
- give every figure and table a label and a caption, and refer to them by name
- cite its sources, data included
- declare its location with
i_am()and read its data withhere() - show no warnings or package start-up messages
- render on a machine that is not yours