This project is a port of the BBC ggplot2 cookbook into vega and vegalite. This
makes use of the gapminder
dataset which is included as a CSV in this
repository. The goal is to have useful examples of vega-lite specifications
recreating the main plots in the BBC cookbook. These should be are easy to
reuse. If getting the last 20% of the visualisation to agree makes up 80% of the
code, then I will opt for only getting it 80% correct. Pull requests are very
welcome provided they agree with the goals of the project.
The =example= directory contains additional examples which replicate graphics produced by the BBC. Again, the goal is not to create a pixel-perfect replication of the original but to get close enough that the differences are the type of thing that one might leave for tidying up with a vector graphics editor.
- =vaccines-given= shows a bar chart of the number of vaccine doses per hundred people.
- =r-over-time= shows a ribbon plot to display the uncertainty in estimates of the effective reproduction number of SARS-CoV-2 in UK.
- =ecdc-covid-cases= shows time series of cases of COVID-19 per capta for several European countries.
- =uk-confirmed-cases= shows a time series of the total number of confirmed SARS-CoV-2 infections on each day in the UK. This example demonstrates how to work with temporal data.
- =us-map-jh= shows a choropleth of the daily average number of COVID-19 cases per million in each state of the US with some annotations. This example demonstrates how to work with spatial data.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": {
"text": "Living longer",
"subtitle": "Life expectancy in Malawi 1952-2007",
"align": "left",
"anchor": "start"
},
"data": {
"url": "gapminder.csv"
},
"transform": [{"filter": "datum.country == 'Malawi'"}],
"mark": "line",
"encoding": {
"x": {
"field": "year",
"type": "temporal",
"timeUnit": "year",
"title": null,
"axis": {"grid": false}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"title": null
}
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": {
"text": "Living longer",
"subtitle": "Life expectancy in China and the US",
"align": "left",
"anchor": "start"
},
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {
"field": "country",
"oneOf": ["China", "United States"]
}
}
],
"mark": "line",
"encoding": {
"x": {
"field": "year",
"type": "temporal",
"timeUnit": "year",
"title": null,
"axis": {"grid": false}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"title": null
},
"color": {
"field": "country",
"type": "nominal",
"title": null
}
},
"config": {
"legend": {"orient": "top"}
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {"field": "year", "equal": 2007}
},
{
"filter": {"field": "continent", "equal": "Africa"}
},
{
"filter": {"field": "lifeExp", "gte": 72}
}
],
"mark": {
"type": "bar",
"color": "#1380A1"
},
"encoding": {
"x": {
"field": "country",
"type": "ordinal",
"sort": "ascending",
"title": null,
"axis": {
"grid": false,
"ticks": false,
"labelAngle": 0
}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"title": null,
"axis": {
"ticks": false,
"domain": false
}
}
},
"title": {
"text": "Reunion is highest",
"subtitle": "Highest African life expectancy, 2007",
"align": "left",
"anchor": "start"
},
"view": {"stroke": null},
"width": 250
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": { "url": "gapminder.csv"},
"transform": [
{"filter": {"field": "year", "equal": 2007}},
{
"calculate": "datum.lifeExp < 50 ? 'Under 50' : (datum.lifeExp < 65 ? '50-65' : (datum.lifeExp < 80 ? '65-80' : '80+'))",
"as": "binnedLifeExp"
}
],
"mark": {
"type": "bar",
"size": 50
},
"width": {
"step": 60
},
"encoding": {
"y": {
"aggregate": "count",
"field": "binnedLifeExp",
"stack": "normalize",
"title": null,
"axis": {
"format": ".1~%",
"domain": false
}
},
"x": {
"field": "continent",
"title": null,
"axis": {
"labelAngle": 0
}
},
"color": {
"field": "binnedLifeExp",
"title": null,
"scale": {
"range": [
"#3B1C8C",
"#21908D",
"#5AC865",
"#F9E721"
],
"domain": [
"Under 50",
"50-65",
"65-80",
"80+"
]
}
}
},
"title": {
"text": "How life expectancy varies",
"subtitle": "% of population by life expectancy band, 2007",
"align": "left",
"anchor": "start"
},
"config": {
"legend": {"orient": "top"}
},
"view": {"stroke": null}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{"filter": {"field": "year", "oneOf": [1967,2007]}},
{"filter": {"field": "country",
"oneOf": [
"Indonesia",
"Libya",
"Oman",
"Vietnam",
"Yemen, Rep."
]}}
],
"mark": "bar",
"encoding": {
"column": {
"field": "country",
"type": "ordinal",
"title": null,
"header": {
"labelOrient": "bottom"
}
},
"x": {
"field": "year",
"type": "ordinal",
"title": null,
"axis": {
"labels": false,
"ticks": false
}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"axis": {
"grid": true,
"domain": false
},
"title": null
},
"color": {
"field": "year",
"type": "ordinal",
"title": null,
"scale": {
"range": [
"#1380A1", "#FAAB18"
]
}
}
},
"config": {
"view": {"stroke": "transparent"},
"legend": {"orient": "top"}
},
"title": {
"text": "We're living longer",
"subtitle": "Biggest life expectancy rise, 1967--2007",
"align": "left",
"anchor": "start"
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{"filter": {"field": "year", "oneOf": [1967,2007]}},
{"filter": {"field": "country",
"oneOf": [
"Indonesia",
"Libya",
"Oman",
"Vietnam",
"Yemen, Rep."
]}}
],
"encoding": {
"y": {
"field": "country",
"type": "ordinal",
"title": null,
"axis": {
"ticks": false,
"domain": false,
"grid": true
}
},
"x": {
"field": "lifeExp",
"type": "quantitative",
"axis": {
"grid": false,
"domain": false,
"ticks": false
},
"scale": {
"zero": false
},
"title": null
},
"color": {
"field": "year",
"type": "ordinal",
"title": null,
"scale": {
"range": [
"#1380A1", "#FAAB18"
]
}
}
},
"layer": [
{
"mark": {
"type": "rule",
"strokeWidth": 5
},
"encoding": {
"x": {
"field": "lifeExp", "aggregate": "min"
},
"x2": {
"field": "lifeExp", "aggregate": "max"
},
"color": {"value": "#dddddd"}
}
},
{
"mark": {
"type": "point",
"filled": true,
"size": 100
}
}
],
"config": {
"view": {"stroke": "transparent"},
"legend": {"disable": true}
},
"title": {
"text": "We're living longer",
"subtitle": "Biggest life expectancy rise, 1967--2007",
"align": "left",
"anchor": "start"
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{"filter": {"field": "year", "equal": 2007}},
{"filter": {"field": "lifeExp", "range": [40,90]}}
],
"mark": "bar",
"encoding": {
"x": {
"bin": true,
"field": "lifeExp",
"title": "Years"
},
"y": {
"aggregate": "count",
"axis": {
"domain": false
},
"title": null
},
"color": {"value": "#1380A1"}
},
"config": {
"view": {"stroke": "transparent"}
},
"title": {
"text": "How life expectancy varies",
"subtitle": "Distribution of life expectancy in 2007",
"align": "left",
"anchor": "start"
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {"field": "year", "equal": 2007}
},
{
"filter": {"field": "continent", "equal": "Africa"}
},
{
"filter": {"field": "lifeExp", "gte": 72}
}
],
"mark": {
"type": "bar",
"color": "#1380A1"
},
"encoding": {
"y": {
"field": "country",
"type": "ordinal",
"sort": "ascending",
"title": null,
"axis": {
"grid": false,
"ticks": false,
"labelAngle": 0
}
},
"x": {
"field": "lifeExp",
"type": "quantitative",
"title": null,
"axis": {
"ticks": false,
"domain": false
},
"scale": {
"domain": [0,200]
}
}
},
"title": {
"text": "Reunion is highest",
"subtitle": "Highest African life expectancy, 2007",
"align": "left",
"anchor": "start",
"dx": 40
},
"view": {"stroke": null},
"width": 250
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": {
"text": "Living longer",
"subtitle": "Life expectancy in China and the US",
"align": "left",
"anchor": "start"
},
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {
"field": "country",
"oneOf": ["China", "United States"]
}
}
],
"encoding": {
"x": {
"field": "year",
"type": "temporal",
"timeUnit": "year",
"title": null,
"axis": {"grid": false},
"scale": {
"domain": [1940,2050]
}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"title": null,
"scale": {
"domain": [0,85]
}
},
"color": {
"field": "country",
"type": "nominal",
"title": null
}
},
"layer": [
{
"mark": "line"
},
{
"transform": [
{"filter": {"field": "year", "equal": {"year": 2007}}}
],
"mark": {
"type": "text",
"align": "left",
"dx": 10
},
"encoding": {
"text": {
"field": "country"
}
}
},
{
"data": {
"values": [
{
"year": 1980,
"lifeExp": 50
}
]
},
"mark": {
"type": "text",
"align": "left"
},
"encoding": {
"text": {
"value": [
"I'm quite a long",
"annotation over",
"three rows"
]
},
"color": {
"value": "black"
}
}
}
],
"config": {
"legend": {"disable": true}
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {"field": "year", "equal": 2007}
},
{
"filter": {"field": "continent", "equal": "Africa"}
},
{
"filter": {"field": "lifeExp", "gte": 72}
},
{
"calculate": "format(datum.lifeExp, 'd')",
"as": "roundedLifeExp"
}
],
"encoding": {
"y": {
"field": "country",
"type": "ordinal",
"sort": "ascending",
"title": null,
"axis": {
"grid": false,
"ticks": false,
"labelAngle": 0
}
},
"x": {
"field": "lifeExp",
"type": "quantitative",
"title": "Years",
"axis": {
"ticks": false,
"domain": false
}
}
},
"layer": [
{
"mark": {
"type": "bar",
"color": "#1380A1"
}
},
{
"mark": {
"type": "text",
"color": "white",
"dx": -15
},
"encoding": {
"text": {
"field": "roundedLifeExp"
}
}
}
],
"title": {
"text": "Reunion is highest",
"subtitle": "Highest African life expectancy, 2007",
"align": "left",
"anchor": "start",
"dx": 40
},
"view": {"stroke": null},
"width": 250
}
To adjust the position of the annotation you can put in a fixed value for x
and then tweak the dx
of the text mark.
{
"mark": {
"type": "text",
"color": "white",
"dx": 10
},
"encoding": {
"x": {
"value": 0
},
"text": {
"field": "roundedLifeExp"
}
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": {
"text": "Living longer",
"subtitle": "Life expectancy in China and the US",
"align": "left",
"anchor": "start"
},
"layer": [
{
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {
"field": "country",
"oneOf": ["China", "United States"]
}
}
],
"mark": "line",
"encoding": {
"x": {
"field": "year",
"type": "temporal",
"timeUnit": "year",
"title": null,
"axis": {
"grid": false,
"ticks": false,
"labelPadding": 10,
"values": [1960,1980,2000]
},
"scale": {
"domain": [1950,2020]
}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"title": null,
"scale": {
"domain": [0,85]
},
"axis": {
"domain": false
}
},
"color": {
"field": "country",
"type": "nominal",
"title": null
}
}
},
{
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {
"field": "country",
"oneOf": ["China", "United States"]
}
},
{
"filter": {
"field": "year",
"equal": {"year": 2007}
}
}
],
"mark": {
"type": "text",
"align": "left",
"dx": 10
},
"encoding": {
"text": {
"field": "country"
},
"x": {
"field": "year",
"type": "temporal",
"timeUnit": "year"
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"title": null,
"scale": {
"domain": [0,85]
}
},
"color": {
"field": "country",
"type": "nominal",
"title": null
}
}
},
{
"data": {
"values": [
{
"year": 1980,
"lifeExp": 60
}
]
},
"mark": {
"type": "text",
"align": "left",
"dy": -20
},
"encoding": {
"text": {
"value": [
"I'm quite a long",
"annotation over",
"three rows"
]
},
"color": {
"value": "black"
}
}
},
{
"data": {
"values": [{}]
},
"encoding": {
"y": {"datum": 10}
},
"mark": {
"type": "rule",
"color": "red",
"strokeDash": [8,8]
}
}
],
"config": {
"legend": {"disable": true}
},
"view": {
"stroke": null
},
"width": 500
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": {
"text": "Asia's rapid growth",
"subtitle": "Population growth by continent 1952-2007",
"align": "left",
"anchor": "start"
},
"data": {
"url": "gapminder.csv"
},
"transform": [
{"filter": "datum.continent != 'Americas'"},
{"groupby": ["continent", "year"],
"aggregate": [{
"op": "sum",
"field": "pop",
"as": "pop_total"
}]
}
],
"mark": "area",
"encoding": {
"x": {
"field": "year",
"type": "quantitative",
"scale": {
"domain": [1950,2010]
},
"title": null,
"axis": null
},
"y": {
"field": "pop_total",
"type": "quantitative",
"title": null,
"axis": {
"format": ".1e"
}
},
"color": {
"field": "continent",
"type": "nominal"
},
"column": {
"field": "continent",
"type": "nominal",
"title": null
}
},
"view": {
"stroke": null
},
"config": {
"legend": {
"disable": true
}
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": {
"text": "It's all relative",
"subtitle": "Relative population growth by continent,1952-2007",
"align": "left",
"anchor": "start"
},
"data": {
"url": "gapminder.csv"
},
"transform": [
{"filter": "datum.continent != 'Americas'"},
{"groupby": ["continent", "year"],
"aggregate": [{
"op": "sum",
"field": "pop",
"as": "pop_total"
}]
}
],
"mark": "area",
"encoding": {
"x": {
"field": "year",
"type": "quantitative",
"scale": {
"domain": [1950,2010]
},
"title": null,
"axis": null
},
"y": {
"field": "pop_total",
"type": "quantitative",
"title": null,
"axis": {
"ticks": false,
"labels": false,
"domain": false
}
},
"color": {
"field": "continent",
"type": "nominal"
},
"facet": {
"field": "continent",
"type": "nominal",
"title": null,
"columns": 2
}
},
"view": {
"stroke": null
},
"config": {
"legend": {
"disable": true
}
},
"resolve": {"scale": {"x": "shared", "y": "independent"}}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "gapminder.csv"
},
"transform": [
{
"filter": {"field": "year", "equal": 2007}
},
{
"filter": {"field": "continent", "equal": "Africa"}
},
{
"filter": {"field": "lifeExp", "gte": 72}
},
{
"calculate": "format(datum.lifeExp, 'd')",
"as": "roundedLifeExp"
},
{
"calculate": "datum.country == 'Mauritius'",
"as": "isMauritius"
}
],
"encoding": {
"y": {
"field": "country",
"type": "ordinal",
"sort": "-x",
"title": null,
"axis": {
"grid": false,
"ticks": false,
"labelAngle": 0
}
},
"x": {
"field": "lifeExp",
"type": "quantitative",
"title": "Years",
"axis": {
"ticks": false,
"domain": false
}
},
"color": {
"field": "isMauritius",
"scale": {
"range": [
"#dddddd", "#1380A1"
]
}
}
},
"mark": {
"type": "bar"
},
"title": {
"text": "Reunion is highest",
"subtitle": "Highest African life expectancy, 2007",
"align": "left",
"anchor": "start",
"dx": 40
},
"config": {
"legend": {
"disable": true
}
},
"view": {"stroke": null},
"width": 250
}
@manual{stylianou2020bbplot,
title = {bbplot: Making ggplot Graphics in BBC News Style},
author = {Nassos Stylianou and Will Dahlgreen and Robert Cuffe and Tom
Calver and Ransome Mpini},
year = 2020,
note = {R package version 0.2},
}
@manual{bryan2017gapminder,
title = {{gapminder: Data from Gapminder}},
author = {Jennifer Bryan},
year = 2017,
note = {R package version 0.3.0},
url = {https://CRAN.R-project.org/package=gapminder},
}