Skip to content

Instantly share code, notes, and snippets.

@g3o2
Last active March 2, 2020 09:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save g3o2/a6c539eacfb0b99eaf01e4f20b9f2897 to your computer and use it in GitHub Desktop.
Save g3o2/a6c539eacfb0b99eaf01e4f20b9f2897 to your computer and use it in GitHub Desktop.
Slope graph à la Edward Tufte
license: bsd-3-clause
height: 1300
border: no

Slopegraph à la Edward Tufte

The slopegraph is described in Edward Tufte's book The Visual Display of Quantitative Information (1983).

This example illustrates this kind of visual display using the barley dataset. The spec should automatically work for multi-year slopegraphs. The key is to manually adjust the first_year and last_year comparison figures (i.e. 1931 and 1932) in the top-level transform, which serve to position the first and last site labels.

The main design issue is to avoid the collision of the labels, in this case for the sites Morris and Grand Rapids in 1931 as well as the sites Morris and Waseca in 1932. Obviously, collision strongly depends on the data and there is no general solution in vega-lite. I have mostly tried to deal with the issue by increasing the height and width parameters - you may find this solution to be extreme. Other solutions are possible:

  • use the size encoding channel to reduce the font size for the yield and site fields;
  • by editing the compiled Vega spec, apply specific production rules for the colliding labels in question, e.g. by reducing only their font size. This is probably the solution you will use if you want a publication-ready visual display;

This block has been forked from Domoritz's Vega-Lite Block example.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega/3.0.7/vega.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega-lite/2.0.0/vega-lite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega-embed/3.0.0-rc7/vega-embed.min.js"></script>
<style>
body {
font-family: sans-serif;
}
.vega-actions a {
padding: 0.2em;
}
</style>
</head>
<body>
<div id="vis"></div>
<script>
const spec = "line_slope.vl.json";
const opt = { renderer: "svg" };
vegaEmbed('#vis', spec, opt);
</script>
</body>
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.0.json",
"height": 1200, "width": 700,
"data": {"url": "https://vega.github.io/vega-datasets/data/barley.json"},
"description": "Slope graph à la Edward Tufte",
"transform": [
{
"aggregate": [ { "op": "sum", "field": "yield", "as": "yield"} ],
"groupby": ["year", "site"]
},
{ "as": "first_year", "calculate": "min(datum.year, 1931)" },
{ "as": "last_year", "calculate": "max(datum.year, 1932)" }
],
"layer": [
{
"mark": "line",
"description": "lines linking the `yield` values",
"encoding": {
"x": {
"field": "year", "type": "ordinal",
"axis": {
"orient": "top", "zindex": 0, "title": "",
"grid": true, "domain": false, "ticks": false, "labels": true,
"labelAngle": 0
}
},
"y": {
"field": "yield", "type": "quantitative", "axis": null,
"scale" : { "zero": false }
},
"detail": { "field": "site", "type": "nominal" },
"color": { "value": "lightgray" },
"size": { "value": 1.5 }
}
},
{
"mark": "circle",
"description": "white circles to contain the `yield` values",
"encoding": {
"x": {
"field": "year", "type": "ordinal",
"axis": {
"orient": "top", "zindex": 0, "title": "",
"grid": true, "domain": false, "ticks": false, "labels": true
}
},
"y": { "field": "yield", "type": "quantitative", "axis": null},
"size": { "value": 400 },
"color": {"value": "white"},
"opacity": { "value": 1 }
}
},
{
"mark": "text",
"description": "`yield` values",
"encoding": {
"x": {
"field": "year", "type": "ordinal",
"axis": {
"orient": "top", "zindex": 0, "title": "",
"grid": true, "domain": false, "ticks": false, "labels": true
}
},
"y": { "field": "yield", "type": "quantitative", "axis": null},
"detail": { "field": "site", "type": "nominal"},
"text": { "field": "yield", "type": "quantitative" },
"color": {"value": "black" },
"size": { "value": 10}
}
},
{
"mark": {"type": "text", "style": "last_name"},
"transform": [ { "filter": "datum.year === datum.last_year"} ],
"description": "last year site label",
"encoding": {
"x": {
"field": "year", "type": "ordinal",
"axis": {
"orient": "top", "zindex": 0, "title": "",
"grid": true, "domain": false, "ticks": false, "labels": true
}
},
"y": { "field": "yield", "type": "quantitative", "axis": null},
"text": { "field": "site", "type": "nominal"},
"size": { "value": 10 },
"color": { "value": "black"}
}
},
{
"mark": {"type": "text", "style": "first_name"},
"transform": [ { "filter": "datum.year === datum.first_year"} ],
"description": "first year site label",
"encoding": {
"x": {
"field": "year", "type": "ordinal",
"axis": {
"orient": "top", "zindex": 0, "title": "",
"grid": true, "domain": false, "ticks": false, "labels": true
}
},
"y": { "field": "yield", "type": "quantitative", "axis": null},
"text": { "field": "site", "type": "nominal"},
"size": { "value": 10 },
"color": { "value": "black"}
}
}
],
"config": {
"view": { "strokeWidth": 0 },
"numberFormat": ".0f",
"axis": {
"gridWidth": 0,
"labelColor": "black", "labelFontSize": 11, "labelAngle": 0
},
"text": { "align": "center", "baseline": "middle"},
"style":{
"last_name" : {"dx": 15, "align": "left", "baseline": "middle"},
"first_name" : {"dx": -15, "align": "right", "baseline": "middle"}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment