Comparison of plotting packages

Well, two immediate things come to my mind:

  1. Suppose we have a Pluto notebook and use a slider to change the value of some parameter. How can we implement it in the original Tex pgfplots package?

  2. Suppose we are dealing with data. The Tex pgfplots package is not very good at dealing with data. We can import it, but I have never liked it that much. Suppose we apply simple operations to our data frame and want to implement them in our plots. How can we do it without the PGFPlotsX.jl?

Indeed, the textbook by Mykel Kochenderfer et al. (linked above) renders the distinction (apparently) useless because the entire book was produced as a monumental piece of code in LaTeX in its final output before printing. However, he and his colleagues are LaTeX virtuosos. Furthermore, somehow, they found it helpful to put Julia, PGFPlots (or PGFPlotsX), and Latex in the same pocket.

Many plotting libraries allow a subset of LaTeX which is translated to Unicode, sub/superscripts, or even fractions. But in PGFPlotsX, you get the full TeX engine for all parts of your plot.

You can also generate TikZ output which can be embedded in your LaTeX document, using the relevant font and size settings for seamless integration.

Whether this is desirable at all depends on the user.


Agree! There are no other julia packages that can be compared to GMT.jl in drawing maps at publication level AFAIK, although GMT.jl is also very good at drawing other kinds of plots.


Makie was what convinced me to completely switch from Python to Julia. Matplotlib and the Python plotting ecosystem was always a pain point. Makie, for me, was simple and the defaults looked great. I was pretty quickly able to get a simple GUI that integrated with my laboratory instruments to automatically spit out plots. The team also does a great job of improving the package. Just my two cents.


One option that wasn’t mentioned above is generating Vega specifications (without Vega.jl). A Vega spec is just JSON.

Here are some additional thoughts on the Vega.jl/VegaLite.jl packages that I think are missing from the blog post:

  • Really strong support for interactive plots. Take a look at the underlying vega and vega-lite docs, the interactive part is really the clue of both of these packages and where a ton of the academic research that powers these packages has been.
  • I don’t think it is right to characterize it as only being integrated with the Queryverse libraries. In fact, there is really no specific integration with Queryverse, both packages just operate on tabular data. Most folks are probably just piping DataFrames into vega-lite plots.
  • I think it is probably the only plotting system for Julia that has an interactive UI for data exploration that one can use to generate plots? With DataVoyager.jl you can pipe your data into an interactive window v = cars |> Voyager(), explore the data interactively and click yourself a plot together, and when you are done you can access the same plot via p = v[], then for example save the plot as a spec p |> save("foo.vegalite") and then at a later time reload the plot and redraw it with new data: newdata |> load("foo.vegalite").
  • I don’t know what the map situation is with the other packages these days, but there is really strong support for plotting data on maps, with lots of support for different projections etc.
  • Documentation is kind of great :wink: The underlying docs for vega and vega-lite are very comprehensive, and given that the Julia wrapper just has minor syntactic tweaks on that it is typically very easy to translate.
  • Great institutional support. There is a fairly large team working on the underlying JavaScript libraries, they constantly add new features, maintain things etc. The Julia wrappers are handled by me, but they are small and automatically pick up new features from upstream. In my experience it is fairly simple to create something that covers like 90% of use-cases, but then you get to the very, very long tail of weird corner cases that folks wants to plot. Having a system that has been around for many, many years with a dedicated team to solve those is really valuable.
  • The split in vega and vega-lite gives folks a ton of control. I’ve never needed to go to the level of vega for any of my plots, but if one needs that level of low-level control, it is there :slight_smile:

There are also some very clear limitations:

  • It is really focused on the grammar of graphics style tabular data plotting. So, no 3D plots for example.
  • It does not work well with very large datasets. That is probably the most annoying thing right now. I do have some ideas on doing better there, but for now one needs to down-sample if one wants to plot millions of plots or something like that.

EDIT: I should clarify that the below observations apply to my experience building visualizations with complex layouts. When one is just interested in a single plot, things are much simpler.

I agree with you, Vega and the ecosystem around it are a really powerful and polished solution for beautiful plotting and other kinds of visualization. It is probably the best choice, certainly so for complex and/or interactive visualization, except for really huge datasets. Vega (Lite) is also great for simple or one-off visualizations, however learning Vega (Lite) can be a huge time sink IMO.

Vega is so feature-rich that it’s sometimes intimidating. The documentation is impressive, but not perfect (missing examples, omissions), and the sheer number of different properties/options can be overwhelming.

Take this manual page, for example. I guess it’s exhaustive, however, and I hope I don’t sound too spoiled saying this, ideally many of the properties there would have example plots next to them. Many manual pages in the Vega docs do, in fact, have examples, my point is just that the docs could be improved a great deal, and then learning Vega would probably be a lot easier for newbies.

One problem that I had, as far as I remember, is that third-party information and tutorials are very scarce, especially for some new features. In fact, it turned out that reading the issues on the Vega and Vega Lite Github sites was the easiest way to learn how some advanced features can be used.

Another complication is that the Julia packages and even Vega Lite (as opposed to pure Vega) add to the abstractions, making learning more difficult if one doesn’t already know Vega in some cases. Debugging Vega Lite can also be difficult for those who don’t know Vega.

The Vega Editor and Vega Embed helped me with learning/experimentation, but jumping straight into HTML/Javascript/CSS is necessary for some advanced features.

To sum up: Vega’s power is a double-edged sword for newbies.

Yes, I would certainly not recommend pure vega/Vega.jl to anyone, unless one has a very specific advanced need. But the good thing is, if one does, it is there. I for once have never used pure Vega.jl in my scientific work, VegaLite.jl always easily did the trick.

If one wants to get started in this ecosystem, VegaLite.jl is the way to go. It scales well beyond one-off figures. We also have way more Julia specific docs for VegaLite.jl than for vega. But I hear you, more Julia specific examples and docs would certainly help.


Is there a plotting package that avoids mutation in its API? Mutation in this context can be e.g. adding a title to an existing plot rather than returning a new one. I see Python’s matplotlib/pyplot as “imperative” and Wolfram Mathematica’s plotting API as “functional”. Is there a Julia package that adopts the latter design?

Yes, VegaLite.jl definitely falls into the non-mutating category. But I think that is true for others as well.

1 Like

Not the case for Plots.jl, whose tutorial shows mutating methods like plot!, xlabel!, title! on the first page. To be fair, I’m much more bothered by matplotlib/pylot’s which assumes a hidden global state.

In GMT that mutating or non-mutating notion doesn’t really make a sense. GMT has what we describe as a layer-cake model. First plot creates a postscript disk file. If that is all user wants the PS file is converted (or not) into PDF or a raster format. But if the figure is not terminated and more elements are needed (e.g., more points, lines, symbols, images, etc…), keep adding them to the layer cake. At the end, do the format conversion.

That sounds super interesting!
Would be willing to share your package?

Yeah, it’s not polished enough for others to use directly. It’s heavily specialized for my experimental workflow. But you’re welcome to try it out. I have a demo that should work.

I also have a small collection of examples of using Makie for interactivity with data and models.


Takafumi actually implemented a similar infrastructure for VegaLite.jl a couple of years ago where one could stream new data into an existing interactive plot: VegaStreams.jl. Not sure whether it still works, might actually be worth reviving if it doesn’t work anymore, it wasn’t much code at all to get that going.

Thanks! Looks great.
Great examples to get started.

1 Like

There is also Deneb.jl announced recently. Plenty of examples can be found in the documentation gallery. Similar to VegaLite.jl, it provides a Julia wrapper to the fantastic Vega-Lite visualization library. It’s pretty new and isn’t battle tested, however I believe (as an unbias author :wink:) that it works well and provides a very nice and elegant API to conveniently produce Vega-Lite visualizations in Julia.

I would appreciate it if you would concider adding a paragraph about Deneb in (the very rough work-in-progress) GitHub - JuliaPackageComparisons/ A website to help Julia users discover and choose between packages :slight_smile:

A bit late, but here is what I think about Plots vs Makie based on my experience with them.

Plots is a wrapper over some other libraries: matplotlib (yes, python), GR etc, see the docs. Plots unifies the usage syntax across these libraries. There are several limitations and the biggest one is that interactivity with the plots is very limited, cause them are created in another language/framework. Another limitation is that the libs do support all the features, e.g. GR is fast but does not have animations, while the others might have animations but are slow, and none of the libs support interactivity. Why would you want to use matplotlib in Julia? It started this way when there were no dedicated plotting packages in Julia, so we had to fallback to python and the other libs.

The time has passed and dedicated plotting packages appeared in Julia and one of them is Makie. Makie is a lot more capable in all aspects: plots, images, 3D rendering and you can also make GUIs(menus, radio-buttons etc). The interactivity is just awesome and also animations are just so easy to create. Good documentation, good support, dedicated discord channel, … and hey : is all Julia.
Just go Makie.


Now, I do not need a lot more capabilities. No is the backend of any relevance for me, be it Julia or Cobol. Actually, Plots offers me all I need and all I can think of that I might need in the future, at least in relation to plotting capabilities. There might be a lot of users like me, some even occasionally use Excel for plotting :face_vomiting: and not ashamed of it.

What I am interested in is ease of use and documentation (and especially ease of use without documentation, if possible).

I didn’t try Makie yet. Should I spent time learning it?