Vega: visualization as code

Today's article will be a short one. I want to share with you a recent discovery: Vega.

In my last blog post, I needed to plot some data. I could use a spreadsheet or another web application and get a sleek visualization. But if I want to make a change, I have to go back to the tool, make the change, export the result, and so on. This is tedious, especially if you have tasted the power of tools that let you code your visualization in the past.

Curious to see how the tools I knew had evolved, I looked at GNUPlot, plot in R, plotting Python libraries like Plotly or Matplotlib, or even Javascript ones like D3.js or Chart.js. Some allow to produce beautiful charts and graphs, but they require to use of a programming language. I would prefer something declarative and specialized like GNUPlot. Still thriving and powerful, GNUPlot is a little bit dusty.

After some searching on the web, I found Vega, sort of the modern heir of GNUPlot. The plotting is defined by a JSON file. There is Vega-lite, a concise variant for common visualization. That just does the job. There is an online editor to build the graph interactively . The icing on the cake, there is a Rust CLI tool, vl-convert to automate the rendering as SVG or PNG.

So for my previous post, I had this simple plot

dev vs maintenance

It is the result of the following Vega-lite

  "$schema": "",
  "title": "development to save maintenance",
  "height": 240,
  "width": 320,
  "data": {
    "values": [
      {"t": "0", "effort": "0", "name": "maintenance"},
      {"t": "30", "effort": "30", "name": "maintenance"},
      {"t": "0", "effort": "0", "name": "maint./2"},
      {"t": "1", "effort": "1", "name": "maint./2"},
      {"t": "2", "effort": "5.5", "name": "maint./2"},
      {"t": "30", "effort": "19.5", "name": "maint./2"},
      {"t": "0", "effort": "0", "name": "0 maint."},
      {"t": "1", "effort": "1", "name": "0 maint."},
      {"t": "2", "effort": "16", "name": "0 maint."},
      {"t": "30", "effort": "16", "name": "0 maint."}
  "mark": "line",
  "encoding": {
    "x": {"field": "t", "type": "quantitative", "title": "month"},
    "y": {"type": "quantitative", "field": "effort", "title": "cumulative effort (in days)"},
    "color": {"field": "name", "type": "nominal"}

I could automate the rendering with vl-convert

vl-convert vl2svg -i "my-plot.vl" -o "my-plot.svg"

which was called each time a change was detected in the Vega-lite file my-plot.vl (see e.g. watchexec).


If you have any comment, question, or feedback, please share them with me.

Atom feed icon Subscribe to the blog!