Session 5: Data Visualization I — the Grammar of Graphics
Monday, 26 October 2026, 09:00–11:15 · Room MAD 099
What this session is about
You have been reading charts for years. In Statistik I and II you never had to build one — and that is the first thing in this course you genuinely have not done before.
The good news is that every chart you will ever make in R is put together from the same handful of parts. A chart is a mapping: this column goes on the x axis, that one on the y axis, a third one decides the colour. Once you can say that sentence, the code follows from it almost word for word. That idea has a name — the grammar of graphics — and it is what ggplot2 is built on.
The other half of the session is choosing. A histogram, a boxplot, a scatter plot and a line chart answer different questions, and most bad charts are not ugly — they are answers to a question nobody asked. So today every chart starts from a question, never from a chart type.
We do this on new data: hotel prices in 46 European cities, which arrive in two files that have to be joined before you can draw anything at all. And the prices are so spread out that the ordinary axis you have used so far stops working — which is where the logarithmic scale, promised since session 1, finally comes in.
Nothing new to install. ggplot2 and forcats come with the tidyverse, and scales — which formats axis labels as euros — is installed along with it:
library(tidyverse)
library(scales)
library(here)Learning goals
- Describe any chart as a mapping from columns to visual properties, in one sentence, before writing code
- Name the parts of a
ggplot— data, aesthetics, geoms, scales, facets — and say which line of code is which - Choose a chart from the question: one distribution, a comparison between groups, a relationship between two numbers, a change over time
- Explain why position is read more accurately than colour or area, and what that means for the charts you choose
- Use a logarithmic axis when the data calls for it, read one correctly, and label it in euros rather than in logarithms
- Show a third variable with colour or with facets, and decide which
- Tell mapping a property (
aes(colour = city)) from setting it (colour = "steelblue") — the most commonggplotbug there is - Join two tables before plotting, and check
non the way
Slides
Materials
| File | Description |
|---|---|
| Exercise sheet | The in-session exercise |
| hotels-europe_price.csv | Prices: one row per hotel and date |
| hotels-europe_features.csv | Features: one row per hotel |
| Slides | Online after the session |
| Live coding document | Online after the session |
| Exemplary solution | Online after the session |
Data
Hotels in Europe — the bigger sibling of the Vienna data you used in sessions 1 to 3, collected the same way from a price comparison website: 22,902 properties in 46 cities, each priced on up to ten different dates between November 2017 and June 2018.
It comes in two files, and neither is enough on its own:
| File | One row is… | Key columns |
|---|---|---|
hotels-europe_price.csv |
one hotel on one date | hotel_id, price, year, month, weekend, nnights |
hotels-europe_features.csv |
one hotel | hotel_id, city, distance, stars, rating, accommodation_type |
The price file knows what a room costs but not where the hotel is; the features file knows where it is but not what it costs. hotel_id is the column they share. That is the join session 2 promised you would need.
Békés and Kézdi (2021), licensed CC BY-NC-SA 4.0. Unmodified.
price is the price for the whole stay, and not every stay is one night. Some December rows are four-night stays, so their price is roughly four times a nightly one. Put all rows into one chart and you are comparing two different units without knowing it.
This is not hidden — it is what the nnights column is for. Today’s exercise works with a single date and a single night throughout, which makes the problem go away. One of the optional tasks asks you to find it the hard way.
The questions we answer
A hotel group that so far only knows Vienna wants to understand the European market. The board has four questions, and each one needs a different chart:
- What does a night in a European hotel typically cost — and is “typical” even a useful word here?
- Which cities are cheap, which are expensive, and by how much?
- Do central hotels charge more everywhere, or only in some cities?
- When in the year is a weekend city break cheapest?
The first question breaks the axis. Prices run from a few euros to several thousand, so on an ordinary axis almost every hotel is squeezed into one bar on the far left. On a logarithmic axis the same data turns into a clean, readable hump — and the answer to “how much more expensive is Stockholm than Istanbul?” becomes a question about ratios, which is the question people were asking all along.
The third question is where the grammar pays off: one extra line of code, facet_wrap(~ city), turns one unreadable chart into eight readable ones — and shows that “central hotels charge more” is true, but by very different amounts in different places.
Take-home until session 6
- Finish the exercise, including the reverse-engineering task — it is the best test of whether the grammar has landed
- Read Wickham et al. (2023), ch. 1 “Data visualization” if you have not, and ch. 9 “Layers” — together about an hour, and they cover everything we did today
- Skim Healy (2018), ch. 1 “Look at data”. It is the argument behind session 6.
Session 6 turns from building charts to communicating with them: titles that state a finding, labels, colour that carries meaning — and the charts that mislead, whether by accident or on purpose. Report 2 is issued at the end of it, and is submitted through GitHub.
Going further
- Wickham et al. (2023), ch. 1, 9, 10 and 11 — visualization, layers, exploratory analysis, communication
- Healy (2018) — the best book-length introduction to
ggplot2for social scientists, free online - Wilke (2019) — which chart for which question, with many good and bad examples side by side. Free online.
- Wickham (2010) — the paper behind
ggplot2, if you want to see where the grammar comes from - The
ggplot2cheat sheet — worth printing