Vega-lite specifications

A Vega-Lite plot specification is represented as a VLSpec object in Julia. There are multiple ways to create a VLSpec object:

  1. The @vlplot macro is the main way to create VLSpec instances in code.
  2. Using the vl string macro, you can write Vega-Lite specifications as JSON in your Julia code.
  3. You can load Vega-Lite specifications from disc with the load function.
  4. The DataVoyager.jl package provides a graphical user interface that you can use to create Vega-Lite specification.

There are two main things one can do with a VLSpec object:

  1. One can display it in various front ends.
  2. One can save the plot to disc in various formats using the save function.

This section will give a brief overview of these options. Other sections will describe each option in more detail.

The @vlplot macro

The @vlplot macro is the main way to specify plots in VegaLite.jl. The macro uses a syntax that is closely aligned with the JSON format of the original Vega-Lite specification. It is very simple to take a vega-lite specification and "translate" it into a corresponding @vlplot macro call. In addition, the macro provides a number of convenient syntax features that allow for a concise expression of common vega-lite patterns. These shorthands give VegaLite.jl a syntax that can be used in a productive way for exploratory data analysis.

A very simple Vega-Lite JSON specification looks like this:

{
  "data": {
    "values": [
      {"a": "A","b": 28}, {"a": "B","b": 55}, {"a": "C","b": 43},
      {"a": "D","b": 91}, {"a": "E","b": 81}, {"a": "F","b": 53},
      {"a": "G","b": 19}, {"a": "H","b": 87}, {"a": "I","b": 52}
    ]
  },
  "mark": "bar",
  "encoding": {
    "x": {"field": "a", "type": "ordinal"},
    "y": {"field": "b", "type": "quantitative"}
  }
}

This can be directly translated into the following @vlplot macro call:

using VegaLite

@vlplot(
    data={
        values=[
            {a="A",b=28},{a="B",b=55},{a="C",b=43},
            {a="D",b=91},{a="E",b=81},{a="F",b=53},
            {a="G",b=19},{a="H",b=87},{a="I",b=52}
        ]
    },
    mark="bar",
    encoding={
        x={field="a", type="ordinal"},
        y={field="b", type="quantitative"}
    }
)

The main difference between JSON and the @vlplot macro is that keys are not surrounded by quotation marks in the macro, and key-value pairs are separate by a = (instead of a :).

While these literal translations of JSON work, they are also quite verbose. The @vlplot macro provides a number of shorthands so that the same plot can be expressed in a much more concise manner. The following example creates the same plot, but uses a number of alternative syntaxes provided by the @vlplot macro:

using VegaLite, DataFrames

data = DataFrame(
    a=["A","B","C","D","E","F","G","H","I"],
    b=[28,55,43,91,81,53,19,87,52]
)

data |> @vlplot(:bar, :a, :b)

Typically you should use these shorthands so that you can express your plots in a concise way. The various shorthands are described in more detail in a different chapter.

The vl string macro

One can embed a JSON vega-lite specification directly in Julia code by using the vl string macro:

using VegaLite

spec = vl"""
{
  "$schema": "https://vega.github.io/schema/vega-lite/v2.json",
  "description": "A simple bar chart with embedded data.",
  "data": {
    "values": [
      {"a": "A","b": 28}, {"a": "B","b": 55}, {"a": "C","b": 43},
      {"a": "D","b": 91}, {"a": "E","b": 81}, {"a": "F","b": 53},
      {"a": "G","b": 19}, {"a": "H","b": 87}, {"a": "I","b": 52}
    ]
  },
  "mark": "bar",
  "encoding": {
    "x": {"field": "a", "type": "ordinal"},
    "y": {"field": "b", "type": "quantitative"}
  }
}
"""

The resulting VLSpec object is indistinguishable from one that is created via the @vlplot macro.

The main benefit of this approach is that one can directly leverage JSON vega-lite examples and code.

Manipulating VLSpec object directly

Vega-Lite properties can be directly accessed as properties of the VLSpec object.

julia> using VegaLite, VegaDatasets

julia> spec = dataset("cars") |>
              @vlplot(:point, x=:Acceleration, y=:Cylinders)

julia> spec.mark
:point

julia> spec.encoding.x.field
"Acceleration"

To modify properties, use Setfield.jl:

julia> using Setfield  # imports `@set` etc.

julia> spec2 = @set spec.mark = :line
       spec3 = @set spec2.encoding.y.field = "Miles_per_Gallon"

Loading and saving vega-lite specifications

The load and save functions can be used to load and save vega-lite specifications to and from disc. The following example loads a vega-lite specification from a file named myfigure.vegalite:

using VegaLite

spec = load("myfigure.vegalite")

To save a VLSpec to a file on disc, use the save function:

using VegaLite

spec = ... # Aquire a spec from somewhere

spec |> save("myfigure.vegalite")

DataVoyager.jl

The DataVoyager.jl package provides a graphical UI for data exploration that is based on vega-lite. One can use that tool to create a figure in the UI, and then export the corresponding vega-lite specification for use with this package here.

Displaying plots

VegaLite.jl integrates into the default Julia multimedia system for viewing plots. This means that in order to show a plot p you would simply call the display(p) function. Most interactive Julia environments (REPL, IJulia, Jupyter Lab, nteract etc.) automatically call display on the value of the last interactive command for you.

Simply viewing plots should work out of the box in all known Julia environments. If you plan to use the interactive features of VegaLite.jl the story becomes slightly more nuanced: while many environments (REPL, Jupyter Lab, nteract, ElectronDisplay.jl, VS Code) support interactive VegaLite.jl plots by default, there are others that either need some extra configuration work (Jupyter Notebook), or don't support interactive plots.

Saving plots

VegaLite.jl plots can be saved as PNG, SVG, PDF, EPS and HTML files. You can save a plot by calling the save function:

using VegaLite, VegaDatasets

p = dataset("cars") |> @vlplot(:point, x=:Horsepower, y=:Miles_per_Gallon)

# Save as PNG file
save("figure.png", p)

# Save as SVG file
save("figure.svg", p)

# Save as PDF file
save("figure.pdf", p)

# Save EPS file
save("figure.eps", p)

# Save HTML file
save("figure.html", p)

You can also use the |> operator with the save function:

using VegaLite, VegaDatasets

dataset("cars") |>
    @vlplot(:point, x=:Horsepower, y=:Miles_per_Gallon) |>
    save("figure.png")