Introducing Quick Plot: ggplot-Style Plotting for Lisp-Stat
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
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)))))
- 50+ new plotting examples for commonly used statistical plots, along with a plotting tutorial.
Data-frame
- Paid technical debt, refactored, made ready for future progress.
- Added
filter-rows,remove-columns,remove-columns!andrename-column!. - Improved unit tests.
- Added column types:
categorical(factor) andtemporal. - Improved error handling, conditions and restarts.
- Working prototypes for
stack,split-apply-combine,sortoperations.
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.