Skip to content

Algorithms

SwarmMakie aims to offer several beeswarm algorithms, which give different results. You can change the algorithm which SwarmMakie uses by passing it as a keyword argument algorithm, or mutating plot.algorithm after the fact.

Currently, it offers the SimpleBeeswarm and WilkinsonBeeswarm algorithms, which are inspired by Matplotlib and Leland Wilkinson's original paper respectively, and a no-op NoBeeswarm algorithm which simply decomposes back to the original data.

In addition, SwarmMakie offers jittered scatter plots as algorithms to beeswarm. These aren't exactly beeswarm plots since they don't guarantee that all points are non-overlapping, but they can still be useful to show distributions, especially for larger numbers of points where all points cannot fit into a beeswarm. These algorithms are accessible as UniformJitter, PseudorandomJitter, and QuasirandomJitter, similar to ggbeeswarm's options.

Comparison

Here's a comparison of all the available algorithms:

julia
using SwarmMakie, CairoMakie
algorithms = [NoBeeswarm() SimpleBeeswarm() WilkinsonBeeswarm(); UniformJitter() PseudorandomJitter() QuasirandomJitter()]
fig = Figure(; size = (800, 450))
xs = rand(1:3, 400); ys = randn(400)
ax_plots = [beeswarm(fig[Tuple(idx)...], xs, ys; color = xs, algorithm = algorithms[idx], markersize = 3, axis = (; title = string(algorithms[idx]))) for idx in CartesianIndices(algorithms)]
jitter_plots = getproperty.(ax_plots[2, :], :plot)
setproperty!.(jitter_plots, :markersize, 7)
setproperty!.(jitter_plots, :alpha, 0.3)
fig

Documentation

SwarmMakie.SimpleBeeswarm Type
julia
SimpleBeeswarm()

A simple implementation like Matplotlib's algorithm.

This algorithm dodges in x but preserves the exact y coordinate of each point. If you don't want to preserve the y coordinate, check out WilkinsonBeeswarm.

source
SwarmMakie.SimpleBeeswarm2 Type
julia
SimpleBeeswarm2()

A simple beeswarm implementation, that minimizes overlaps. This is the default algorithm used in beeswarm.

This algorithm dodges in x but preserves the exact y coordinate of each point. If you don't want to preserve the y coordinate, check out WilkinsonBeeswarm.

source
SwarmMakie.WilkinsonBeeswarm Type
julia
WilkinsonBeeswarm()

A beeswarm algorithm that implements Leland Wilkinson's original dot-hist algorithm.

This is essentially a histogram with dots, where all dots are binned in the y (non-categorical) direction, and then dodged in the x (categorical) direction.

Original y-coordinates are not preserved, and if you want that try SimpleBeeswarm instead.

source
SwarmMakie.NoBeeswarm Type

A simple no-op algorithm, which causes the scatter plot to be drawn as if you called scatter and not beeswarm.

source

Code exists for the algorithm suggested by Michael Borregaard in this StatsPlots.jl PR, but it is currently nonfunctional. If you'd like to take a crack at getting it working, please do!

SwarmMakie.UniformJitter Type
julia
UniformJitter(; jitter_width = 1.0)

A jitter algorithm that uses a uniform distribution to create the jitter.

source
SwarmMakie.PseudorandomJitter Type
julia
PseudorandomJitter(; jitter_width = 1.0)

A jitter algorithm that uses a pseudorandom distribution to create the jitter. A pseudorandom distribution is a uniform distribution weighted by the PDF of the data.

source
SwarmMakie.QuasirandomJitter Type
julia
QuasirandomJitter(; jitter_width = 1.0)

A jitter algorithm that uses a quasirandom (van der Corput) distribution weighted by the data's pdf to jitter the data points.

source

We also welcome any new algorithms you may have in mind. Just open a PR!

Adding a new algorithm

In order to add a new algorithm, you must simply define a struct which subtypes SwarmMakie.BeeswarmAlgorithm.

There must also be a corresponding dispatch on SwarmMakie.calculate!(buffer, alg, positions, markersize) which loads the new positions calculated in pixel space into buffer. Note that buffer must be modified here.

See the Wilkinson source page for a deep dive into how to write a beeswarm algorithm!