Skip to main content

p9beeswarm

p9beeswarm provides beeswarm-style geoms for plotnine, modelled after the R ggbeeswarm package. The distribution also exposes the upstream algorithm compatibility modules as beeswarm and vipor, mirroring the corresponding R packages.

Upstream R tools

p9beeswarm is heavily inspired by the following upstream R packages. The Python implementations and compatibility tests follow their algorithms and plotting behavior:

Package License Authors
beeswarm Artistic License 2.0 Aron Eklund, James Trimble, et al.
vipor GPL (>= 2) Scott Sherrill-Mix, Erik Clarke, et al.
ggbeeswarm GPL (>= 3) Erik Clarke, Scott Sherrill-Mix, Charlotte Dawson, et al.

Installation

Install p9beeswarm from PyPI with:

python -m pip install p9beeswarm

Usage

import plotnine as p9
from plotnine.data import penguins
from p9beeswarm import geom_quasirandom

penguins_plot = (
    p9.ggplot(
        penguins,
        p9.aes(x="species", y="body_mass_g", color="species"),
    )
    + geom_quasirandom()
    + p9.labs(
        title="Penguin body mass by species",
        x="Species",
        y="Body mass (g)",
    )
    + p9.theme_bw()
)

Rendered output:

Penguin body mass beeswarm plot by p9beeswarm

The side-by-side ggbeeswarm examples recreate the upstream README plots with both the Python and R implementations. Render them with:

quarto render docs/ggbeeswarm-examples.qmd

The README figure is generated by docs/update_readme_figure.py. If you change the example above, regenerate the image with:

uv run python docs/update_readme_figure.py

Implementations and reproducibility

The table below records the Python implementation and its upstream R implementation. “100% reproducible” means that repeated builds with the same data and parameters do not draw random numbers. Methods marked as random can still be made reproducible in Python by passing a fixed random_state; without one, their point positions may change between builds.

Plotnine API / method Upstream R implementation 100% reproducible? Notes
geom_quasirandom(method="quasirandom") ggbeeswarm::geom_quasirandom → vipor::offsetX / vipor::offsetSingleGroup Yes Uses the deterministic van der Corput sequence. This is the default quasirandom method.
geom_quasirandom(method="maxout|minout|smiley|frowney") ggbeeswarm::geom_quasirandom → vipor::offsetX / vipor::offsetSingleGroup Yes Density and alternating extreme placement do not use random draws.
geom_quasirandom(method="pseudorandom") ggbeeswarm::geom_quasirandom → vipor::offsetX / vipor::offsetSingleGroup No (unless seeded) Explicitly generates random offsets; pass random_state for repeatable Python plots.
geom_quasirandom(method="tukey|tukeyDense") ggbeeswarm::geom_quasirandom → vipor::offsetX / vipor::tukeyTexture No (unless seeded) Tukey texture generates random permutations and jitter; pass random_state for repeatable Python plots.
geom_beeswarm(method="swarm") ggbeeswarm::geom_beeswarm → beeswarm::swarmx Yes* The default priority="ascending" and corral="none" are deterministic. priority="random" or corral="random" introduces randomness.
geom_beeswarm(method="compactswarm") ggbeeswarm::geom_beeswarm → beeswarm::swarmx(compact=TRUE) Yes* Same priority and corral caveat as swarm.
geom_beeswarm(method="center|square|hex") ggbeeswarm::geom_beeswarm internal grid placement (center, square, or hex) Yes* Grid placement is deterministic; corral="random" is the exception.

*The beeswarm rows are deterministic with their default options. Any method that uses a random priority or corral is not 100% reproducible unless a seed is supplied.

License

p9beeswarm is licensed under the GNU GPLv3 or later.

Testing

The package is managed with [uv]. The core test suite covers the beeswarm and vipor compatibility modules, along with the plotnine position/geom integration:

uv run --no-default-groups --group test pytest

Upstream comparison tests

Beyond the core suite, the tests include parity checks against the original R packages. These tests use rpy2 to call the upstream R implementations and assert that the Python results match numerically:

uv run --no-default-groups --group test --group r-test pytest

The R dependencies are pinned in renv.lock and restored by the GitHub Actions workflow with r-lib/actions/setup-renv. To update the pinned versions, run these commands from the repository root:

Rscript -e 'if (!requireNamespace("renv", quietly = TRUE)) install.packages("renv", repos = "https://cloud.r-project.org")'
Rscript -e 'renv::restore(prompt = FALSE)'
Rscript -e 'renv::update(c("beeswarm", "vipor", "ggbeeswarm", "ggplot2"), prompt = FALSE)'
Rscript -e 'renv::snapshot(prompt = FALSE)'

Review the resulting renv.lock diff, run the upstream comparison tests, and commit the updated lockfile along with any dependency changes.

Type checking

Type-check using mypy.

uv run --no-default-groups --group test --group r-test mypy src/ tests/

Metadata

Release files for p9beeswarm 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for p9beeswarm 0.3.0
File Size Uploaded
p9beeswarm-0.3.0.tar.gz 30.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for p9beeswarm 0.3.0
File Interpreter ABI Platform
p9beeswarm-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 63.1 kB

Release files / p9beeswarm-0.3.0.tar.gz

Download URL p9beeswarm-0.3.0.tar.gz
Size 30.8 kB
Tags Source
SHA-256 checksum
How to use checksums
ff94384f3a1683c01093c762614407929389d4995a321d755216889cf535c22e
BLAKE2b-256 checksum
How to use checksums
cd1a354ec3a1c2ac4720a7d2186e79d4b6285c2f40e49b050311433a9d89cffe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / p9beeswarm-0.3.0-py3-none-any.whl

Download URL p9beeswarm-0.3.0-py3-none-any.whl
Size 32.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
53bd9898aa9116ea2a70567cad566f6d9b1860da96d631dce99aef7d02e848d9
BLAKE2b-256 checksum
How to use checksums
e98049d0830294dbe466cf9e5b860e434de416144cc609425afccdcbf4b56e76
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page