Skip to content

Commit 1da8d57

Browse files
feat(letsplot): implement swarm-basic (#9940)
## Implementation: `swarm-basic` - python/letsplot Implements the **python/letsplot** version of `swarm-basic`. **File:** `plots/swarm-basic/implementations/python/letsplot.py` **Parent Issue:** #974 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/30192305995)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent a243786 commit 1da8d57

2 files changed

Lines changed: 138 additions & 144 deletions

File tree

plots/swarm-basic/implementations/python/letsplot.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
""" anyplot.ai
22
swarm-basic: Basic Swarm Plot
3-
Library: letsplot 4.9.0 | Python 3.13.13
4-
Quality: 80/100 | Updated: 2026-05-05
3+
Library: letsplot 4.11.0 | Python 3.13.14
4+
Quality: 93/100 | Updated: 2026-07-26
55
"""
66

7+
import os
8+
79
import numpy as np
810
import pandas as pd
911
from lets_plot import (
1012
LetsPlot,
1113
aes,
1214
element_blank,
1315
element_line,
16+
element_rect,
1417
element_text,
1518
geom_crossbar,
1619
geom_sina,
20+
geom_violin,
1721
ggplot,
1822
ggsave,
1923
ggsize,
@@ -27,12 +31,20 @@
2731

2832
LetsPlot.setup_html()
2933

34+
# Theme-adaptive chrome tokens (Imprint palette + surface tokens)
35+
THEME = os.getenv("ANYPLOT_THEME", "light")
36+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
37+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
38+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
39+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
40+
41+
IMPRINT_PALETTE = ["#009E73", "#C475FD", "#4467A3", "#BD8233"]
42+
3043
# Data - Performance scores across departments
3144
np.random.seed(42)
3245

3346
departments = ["Engineering", "Marketing", "Sales", "Support"]
3447
n_per_group = [45, 38, 52, 40]
35-
colors = ["#306998", "#FFD43B", "#2E8B57", "#DC143C"]
3648

3749
data = []
3850
for dept, n in zip(departments, n_per_group, strict=True):
@@ -59,31 +71,37 @@
5971
means = df.groupby("Department")["Performance Score"].mean().reset_index()
6072
means.columns = ["Department", "mean"]
6173

74+
title = "swarm-basic · python · letsplot · anyplot.ai"
75+
6276
# Plot
6377
plot = (
6478
ggplot(df, aes(x="Department", y="Performance Score"))
79+
+ geom_violin(aes(fill="Department"), alpha=0.15, trim=False, show_legend=False)
6580
+ geom_sina(aes(color="Department", fill="Department"), size=4, alpha=0.7, seed=42, scale="width")
66-
+ geom_crossbar(
67-
aes(x="Department", y="mean", ymin="mean", ymax="mean"), data=means, width=0.5, size=1.5, color="#333333"
68-
)
69-
+ scale_color_manual(values=colors)
70-
+ scale_fill_manual(values=colors)
71-
+ labs(x="Department", y="Performance Score", title="swarm-basic · letsplot · pyplots.ai")
81+
+ geom_crossbar(aes(x="Department", y="mean", ymin="mean", ymax="mean"), data=means, width=0.5, size=1.5, color=INK)
82+
+ scale_color_manual(values=IMPRINT_PALETTE)
83+
+ scale_fill_manual(values=IMPRINT_PALETTE)
84+
+ labs(x="Department", y="Performance Score (0-100)", title=title)
7285
+ theme_minimal()
7386
+ theme(
74-
plot_title=element_text(size=24, face="bold"),
75-
axis_title=element_text(size=20),
76-
axis_text=element_text(size=16),
87+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
88+
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
89+
panel_border=element_blank(),
90+
legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),
91+
plot_title=element_text(size=16, face="bold", color=INK),
92+
axis_title=element_text(size=12, color=INK),
93+
axis_text=element_text(size=10, color=INK_SOFT),
94+
axis_line=element_line(color=INK_SOFT),
7795
legend_position="none",
7896
panel_grid_major_x=element_blank(),
7997
panel_grid_minor=element_blank(),
80-
panel_grid_major_y=element_line(color="#cccccc", size=0.5),
98+
panel_grid_major_y=element_line(color=INK_SOFT, size=0.3),
8199
)
82-
+ ggsize(1600, 900)
100+
+ ggsize(800, 450)
83101
)
84102

85-
# Save PNG (scale=3 gives 4800x2700)
86-
ggsave(plot, "plot.png", path=".", scale=3)
103+
# Save PNG (scale=4 gives 3200x1800)
104+
ggsave(plot, f"plot-{THEME}.png", path=".", scale=4)
87105

88106
# Save HTML for interactive version
89-
ggsave(plot, "plot.html", path=".")
107+
ggsave(plot, f"plot-{THEME}.html", path=".")

0 commit comments

Comments
 (0)