Introducing Quick Plot: ggplot-Style Plotting for Lisp-Stat

Composable, ggplot-inspired plotting helpers

Today we’re releasing quick-plot, a new system for Lisp-Stat that bring ggplot2-style composable plotting to Common Lisp. plot/vega is able to render any Vega-Lite specification (here’s 50 examples), but it can at times be a bit wordy constructing the nested plists by hand.

Overview

Instead of specifying each plot in detail, quick-plot provides a set of helper functions that work similarly to geom in ggplot. Essentially we borrow ggplot’s concept of a plot as a composition of independent layers (which is what Vega-Lite does anyway), each with one concern:

Function Package Responsibility
point geom Scatter plot mark & encoding
bar geom Bar chart mark & encoding
histogram geom Binned distribution
box-plot geom Summary statistics
line geom Line chart mark & encoding
label gg Axis titles
axes gg Scales, transforms, domains
coord gg Viewport clipping
theme gg Dimensions, fonts, style
tooltip gg Hover details

Each function returns a plist fragment. A recursive merge-plists combines them into a single Vega-Lite spec. A mark function never sets axis titles; label never touches encodings; theme never alters mark types. You can add, remove, or swap any layer without affecting the others.

Simple example

Setup environment:

(asdf:load-system :quick-plot)
(vega:load-vega-examples)

(import '(geom:point geom:bar geom:histogram geom:box-plot geom:line))
(import '(gg:label gg:axes gg:coord gg:theme gg:tooltip))
(import '(qplot:qplot))

Basic scatter plot

The simplest scatter plot needs just a name, a data frame, and two field names:

(qplot 'cars-basic vgcars
  `(:title "Horsepower vs. MPG")
   (point :horsepower :miles-per-gallon))

Add labels

Scatter plot with labels:

(qplot 'blog-labels vgcars
  `(:title "Vega Cars")
   (point :horsepower :miles-per-gallon :filled t)
   (label :x "Engine Horsepower" :y "Fuel Efficiency (MPG)"))

Get fancy

Now you can add size of the point to encode some data, along with color:

(qplot 'cars-bubble vgcars
  `(:title "Bubble: Size = Acceleration")
   (point :horsepower :miles-per-gallon
          :color :origin :size :acceleration
          :filled t)
   (label :x "Horsepower" :y "Miles per Gallon"))

Get started

See the quick-plot cookbook for recipes for some common plot types.

2022 Release

Lisp-Stat 1.0.0

Overview

This release is the third major refactoring of Lisp-Stat, with particular emphasis on plotting. I have attempted to make plotting as easy in Lisp-Stat as it is in Vega-Lite, upon which it is based. In addition, much clean-up and polishing of sharp edges has taken place as a result of using Lisp-Stat on real-world projects.

As always, comments and contributions are welcome.

What’s New

Lisp-Stat

  • Data loading functions akin to R’s data function. You can now load the Lisp-Stat data sets with this function, e.g. (data :mtcars). The mechanism is extensible for add on packages to use as well.
  • Additional cleansed and annotated data sets included.

Plot

  • The plotting system has been completely reworked. For example, to create a scatter plot of horsepower vs. miles per gallon:
(asdf:load-system :plot/vega)
(data :vgcars)
(plot:plot
  (vega:defplot hp-mpg
  `(:title "Horsepower vs. MPG"
    :data (:values ,vgcars)
    :mark :point
	:encoding (:x (:field vgcars:horsepower)
	           :y (:field vgcars:miles-per-gallon)))))

Data-frame

  • Paid technical debt, refactored, made ready for future progress.
  • Added filter-rows, remove-columns, remove-columns! and rename-column!.
  • Improved unit tests.
  • Added column types: categorical (factor) and temporal.
  • Improved error handling, conditions and restarts.
  • Working prototypes for stack, split-apply-combine, sort operations.

Array Operations

Array operations has been rehomed and now lives in the Lisp-Stat github organisation. Significant improvements to documentation over the previous repository.

Documentation

There probably isn’t a part of the documentation that hasn’t been touched. Improvements in all areas, including organisation, expanded topic coverage and quality improvements.

Semantic Versioning

Previously Lisp-Stat used semantic versioning appropiate for binary patch distribution. In this scheme the major number indicates whether or not the lisp image needed to be cold started, and a minor version indicating if a patch could be applied. Since it’s unlikely we’ll have a viable patching system in the open source Common Lisp world anytime soon, we’ve moved to semantic versioning for source releases. Since the semantics of versioning are different, all systems have been reset to 1.0.0. Going forward we’ll use the major.minor.patch scheme.