plotlet v0.6.2

swarm

Categorical

["a","b","c"]

Minimal call

import random
rng = random.Random(2)
data = {"grp": [], "value": []}
for i, grp in enumerate(["a", "b", "c"]):
    data["grp"] += [grp] * 40
    data["value"] += [rng.gauss(4 + i, 0.8) for _ in range(40)]

c = pt.chart(data, aes(x="grp", y="value"), ylabel="value")
c.add_swarm(size=2.2)

Worked example

["Thur","Fri","Sat","Sun"]
import plotlet as pt
from plotlet import aes

df = pt.load_dataset("tips")

c = pt.chart(df, aes(x="day", y="tip", fill="sex"),
             title="tips by day", ylabel="tip ($)",
             data_width=380, data_height=220)
c.xscale("category", order=["Thur", "Fri", "Sat", "Sun"])
c.add_swarm(size=2.2)

Docstring

Bee-swarm plot: categorical scatter with greedy non-overlapping point placement.

Long-form only:
  c.add_swarm(aes(x="cat", y="value"))
  c.add_swarm(aes(x="cat", y="value", fill="group"), palette={...})

Mapping `aes(fill="col")` dodges sub-swarms side-by-side within each cat
and emits one legend entry per group level.

Aesthetics:
  fill=<literal>        bare literal point color (None = cycle default);
                        aes(fill="col") → column-driven grouping
  color=<literal>       point outline (defaults to frame color when used)
  palette=              maps group levels → fills when fill is mapped in aes

Other styling kwargs:
  orientation='v'   'h' for horizontal (cats on y axis)
  width=0.8         total dodge-group width as a band fraction
  gap=0.1           slot-gap fraction between dodged sub-swarms
  size=3            point radius in pixels
  alpha=0.9         point opacity
  linewidth=0       outline stroke width (0 = no outline)
  rasterize=None    None = auto-raster to one <image> above the point
                    threshold; True/False forces it on/off