[ANN] VegaLite.jl v2.0 released

We released VegaLite.jl v2.0 a couple of days ago. This new version brings a lot of new features along! I’ll try to walk you through some of them in this post.

For those of you not familiar with the package: VegaLite.jl is a powerful plotting package for Julia.

Vega-Lite 4

We updated the Julia package to use the latest version of the underlying JavaScript library, Vega-Lite 4. This brings a ton of new features to the table. You can take a look at a detailed description of all these updates by looking at the release notes for all the Vega-Lite versions we now incorporate:

I encourage you to take a look at these release notes, they have examples for each new feature and give a good overview of what is happening in the underlying library. There is a lot of good stuff (regression, loess, density and quantile transforms, a strokeDash encoding channel, lots of new interactive stuff and a ton of other features)!

Support for inline data

We now support inline data, i.e. you can now create a plot from vectors of data directly, without the need to pass a tabular data structure like DataFrame to the plot function. The following example plots a scatter plot of two vectors of random numbers:


using VegaLite

a_vector = rand(10)

@vlplot(:point, x=rand(10), y=a_vector)

You can also pass vectors inside a composite value:


using VegaLite 

@vlplot(:line, x={1:10, title="Timestep"}, y=rand(10))

Support for positional x and y encodings

The values for the x and y encoding channel can now be passed as positional arguments, thus further reducing the amount of code required for common plots.

In particular, the second positional argument is now interpreted as the x channel, and the third positional argument as the y channel.

A simple example that uses some tabular data is this:


using VegaLite, VegaDatasets

dataset("cars") |> @vlplot(:point, :Acceleration, :Miles_per_Gallon)

The combination of positional arguments and inline data makes the code for a simple scatter plot of two vectors really concise:


using VegaLite

a = rand(10)

b = rand(10)

@vlplot(:point, a, b)

Save plots as HTML files

You can now save a plot directly as a HTML file:


using VegaLite

@vlplot(:point, rand(10), rand(10)) |> save("figure.html")

These HTML files are self contained, and are especially useful for interactive charts (which will fully work if someone opens the generated HTML file in a web browser).

Much better support for Vega specs

The package now exports a new @vgplot macro. It works exactly like @vlplot, except that you can use it to create Vega plots. Vega is the lower-level plotting library that Vega-Lite uses under the hood. It is more verbose than Vega-Lite, but gives you much more control over the types of plots you can create. Take a look at the Vega examples to get a sense.

Better Juno integration

Interactive plots should now work properly in Juno.

Convert plots into Julia code (experimental)

You can now take a plot object and call a function to get some Julia code that would re-create exactly that plot object. Here is a simple example:


using VegaLite, VegaDatasets

p = dataset("cars") |> @vlplot(:point, :Acceleration, :Miles_per_Gallon)

VegaLite.printrepr(stdout, p)

This will output:


@vlplot(mark="point",encoding={x={field="Acceleration"},y={field="Miles_per_Gallon"}})

This standalone example is probably not very useful, but this functionality can be very convenient if you obtain the plot from some other source.

For example, here is an example where you copy a Vega-Lite JSON example and convert it into an equivalent Julia code representation:


using VegaLite

p = vl"""

{

    "mark": "point",

    "encoding": {

        "x": {

            "field": "Miles_per_Gallon"

        },

        "y": {

            "field": "Acceleration"

        }

    }

}

"""

VegaLite.printrepr(stdout, p)

This also outputs the Julia code that would create this spec:


@vlplot(encoding={x={field="Miles_per_Gallon"},y={field="Acceleration"}},mark="point")

Another scenario is that you load a Vega-Lite spec from disc and directly convert it into Julia code:


using VegaLite

VegaLite.printrepr(stdout, load("figure.vegalite"))

Or maybe you used DataVoyager.jl to interactively create a plot and now want to include some code that creates that same figure, but in a non-interactive way:


using DataVoyager, VegaDatasets

# Run Voyager

w = dataset("cars") |> Voyager()

# At this point you would interactively create your plot and proceed once you are done with that

# Extract the plot from the UI

p = w[]

# Convert the interactively created plot into Julia code

VegaLite.printrepr(stdout, p)

New examples

We have a ton of new examples, both for Vega and Vega-Lite plots in the documentation, check them out here!

New expert APIs (experimental)

We now also export a purely non-macro based API. The two functions for that are vlplot and vgplot. Normal users are encouraged to continue to use the @vlplot and @vgplot macros, these new functions are mostly meant for some special situations where other packages can’t use the macro versions of these calls.

We also export new macros and functions called @vlfrag, @vgfrag, vlfrag and vgfrag. These allow you to create spec fragments and then pass these to the main level @vlplot, @vgplot, vlplot and vgplot macros and functions.

For example, in this example I break up the call to @vlplot into two calls by using the @vlfrag macro:


using VegaLite, VegaDatasets

x_frag = @vlfrag(:Miles_per_Gallon, title="Custom title")

dataset("cars") |> @vlplot(:point, x=x_frag)

We again discourage use of this feature in normal user code, this is another feature that is probably most useful for package authors that want to make use of VegaLite.jl.

Bug fixes and performance

There are a ton of bug fixes and performance improvements in this version:

  • We handle inline data much more efficiently

  • We auto-encode encoding types in sub specs

  • We properly apply shorthands in sub specs

Thanks

This release had a lot of folks contributing, I in particular want to thank oheil, mcmcgrath13 and tkf for their help!

Cross posted from the queryverse blog.

40 Likes

Great stuff. In particular being able to easily plot raw vectors and pass them positionally seems like a great usability improvement for simple plots.

I think one of the things that prevented me from using VegaLite before was that the underlying vega library didn’t have an efficient way to display high-resolution heatmap data, which I do a lot. As of v5.8, released last november, now there’s the heatmap transform, which seems like it should do nicely.

Looking forward to checking this out.

1 Like

Yes, I think that should be feasible to do now. And support for this is probably going to come to Vega-Lite as well, see here.

2 Likes

@vlplot(:line, x={1:10, title="Timestep"}, y=rand(10)) dosn’t really work. I get a ArgumentError: Invalid type. error

@affans, are you sure you have VegaLite.jl v2 on your system? The exact code you posted works fine on my system.