Data visualisation with Vega-Lite and a hugo/markdown based website

Implementing a Vega-Lite interactive visualisation within a markdown based website

Posted by Joe O'Reilly on Saturday, July 24, 2021

Data visualisation with Vega-Lite and a hugo/markdown based website

I recently learned how to use Vega-Lite to produce data visualisations; Vega-Lite offers a ‘grammar of graphics’ style approach to web-based graphics. A nice benefit of this approach is that we can draw visualisations using SVG and incorporate interactivity if the visualisation is deployed online.

In this example I have applied Vega-Lite to the data from TidyTuesday 2021 week 19, on the subject of water source surveying. The visualisation isn’t particularly informative, but does show how easy it is to generate a complete and well styled interactive visualisation with minimal effort.


Water Points Recorded By WPDX Across Africa

Each tile represents a single african nation and is coloured according to the number of water points recorded for that nation by WPDX


Embedding the visualisation

The visualisation is embedded in the page by writing the necessary html code directly into the .Rmd document.

This is achieved by first importing the relevant libraries.

<head>
  <!-- Import Vega & Vega-Lite -->
  <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
  <script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
  <!-- Import vega-embed -->
  <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
</head>

Then I specify a div in which the visualisation will reside.

<div id="vis"></div>

The div is then selected and the json that defines the Vega-Lite visualisation is called. The actual data the visualisation is generated from (cleaned.csv) is simply stored within the same post directory as the .Rmd file used to generate the html output.


<script type="text/javascript">
  vegaEmbed('#vis', {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "width": 200, "height": 200,
    "padding": {"left": 20, "top": 20, "right": 50, "bottom": 20},
    "background": "#FBFFF1",
    "view": {"fill": "#FBFFF1", "stroke" : null},
    "data": {"url": "cleaned.csv"},
    "transform": [
      {"calculate": "datum.row", "as": "row"}
    ],
    "layer":[
      {
        "mark": "rect",
        "encoding": {
          "y": {
            "type": "ordinal",
            "field": "row",
            "axis": false},
          "x": {
            "field": "col",
            "type": "ordinal",
            "axis": false},
          "color": {
              "field": "N",
              "scale": {
                "type": "threshold",
                "domain": [10, 100, 1000, 10000, 100000]
               },
               "type": "quantitative",
               "title": ["Number of", "Reported Water Points"]},
          "stroke": {
            "value": "black"}, 
          "tooltip": [
            {"field": "N", "type": "nominal", "title": "Number of reports"},
            {"field": "name", "type": "nominal", "title": "Country"}
          ]
          }
    },
      {
        "mark": {"type": "text", "fontSize": 8}, 
        "encoding": {
          "text": {"field": "code", "type": "nominal"},
          "y": {
            "type": "ordinal",
            "field": "row",
            "axis": false},
          "x": {
            "field": "col",
            "type": "ordinal",
            "axis": false},
          "color": {
            "condition": {"test": "datum['N'] < 10000000", "value": "black"},
            "value": "white"
          },
          "tooltip": [
            {"field": "N", "type": "nominal", "title": "Number of reports"},
            {"field": "name", "type": "nominal", "title": "Country"}
          ]
        }
      }
    ], 
      "config": {
        "font": "Bebas"
      }
    }
  
  , {"actions": false}).then(function(result) {
    // Access the Vega view instance (https://vega.github.io/vega/docs/api/view/) as result.view
  }).catch(console.error);
</script>