Skip to content

Commit f395471

Browse files
feat(letsplot): implement waffle-basic (#1050)
## Implementation: `waffle-basic` - letsplot Implements the **letsplot** version of `waffle-basic`. **File:** `plots/waffle-basic/implementations/letsplot.py` **Parent Issue:** #998 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20260266028)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent f89a8a3 commit f395471

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
waffle-basic: Basic Waffle Chart
3+
Library: letsplot
4+
"""
5+
6+
import pandas as pd
7+
from lets_plot import (
8+
LetsPlot,
9+
aes,
10+
coord_fixed,
11+
element_blank,
12+
element_text,
13+
geom_tile,
14+
ggplot,
15+
ggsize,
16+
labs,
17+
scale_fill_manual,
18+
theme,
19+
theme_void,
20+
)
21+
from lets_plot.export import ggsave
22+
23+
24+
LetsPlot.setup_html()
25+
26+
# Data - Market share by category (values sum to 100%)
27+
categories = ["Product A", "Product B", "Product C", "Product D"]
28+
values = [42, 28, 18, 12] # Percentages
29+
30+
# Colors - Python Blue first, then colorblind-safe palette
31+
colors = ["#306998", "#FFD43B", "#4CAF50", "#FF7043"]
32+
33+
# Build 10x10 waffle grid (100 squares, each = 1%)
34+
# Fill from top-left, row by row
35+
grid_data = []
36+
square_idx = 0
37+
38+
for cat, val in zip(categories, values, strict=True):
39+
for _ in range(val):
40+
row = 9 - (square_idx // 10) # Start from top (row 9) going down
41+
col = square_idx % 10
42+
grid_data.append({"x": col, "y": row, "category": cat})
43+
square_idx += 1
44+
45+
df = pd.DataFrame(grid_data)
46+
47+
# Preserve category order for legend
48+
df["category"] = pd.Categorical(df["category"], categories=categories, ordered=True)
49+
50+
# Create legend labels with percentages
51+
legend_labels = {cat: f"{cat} ({val}%)" for cat, val in zip(categories, values, strict=True)}
52+
df["legend_label"] = df["category"].map(legend_labels)
53+
df["legend_label"] = pd.Categorical(
54+
df["legend_label"], categories=[legend_labels[cat] for cat in categories], ordered=True
55+
)
56+
57+
# Plot
58+
plot = (
59+
ggplot(df, aes(x="x", y="y", fill="legend_label"))
60+
+ geom_tile(width=0.9, height=0.9, size=0)
61+
+ coord_fixed(ratio=1)
62+
+ scale_fill_manual(values=colors)
63+
+ labs(title="waffle-basic · letsplot · pyplots.ai", fill="Category")
64+
+ theme_void()
65+
+ theme(
66+
plot_title=element_text(size=24, hjust=0.5),
67+
legend_title=element_text(size=18),
68+
legend_text=element_text(size=16),
69+
axis_title=element_blank(),
70+
axis_text=element_blank(),
71+
)
72+
+ ggsize(1600, 900)
73+
)
74+
75+
# Save PNG (scale=3 gives 4800x2700)
76+
ggsave(plot, "plot.png", path=".", scale=3)
77+
78+
# Save HTML for interactivity
79+
ggsave(plot, "plot.html", path=".")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Per-library metadata for letsplot implementation of waffle-basic
2+
# Auto-generated by impl-generate.yml
3+
4+
library: letsplot
5+
specification_id: waffle-basic
6+
7+
# Preview URLs (filled by workflow)
8+
preview_url: https://storage.googleapis.com/pyplots-images/plots/waffle-basic/letsplot/plot.png
9+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/waffle-basic/letsplot/plot_thumb.png
10+
preview_html: https://storage.googleapis.com/pyplots-images/plots/waffle-basic/letsplot/plot.html
11+
12+
current:
13+
version: 0
14+
generated_at: 2025-12-16T07:46:50Z
15+
generated_by: claude-opus-4-5-20251101
16+
workflow_run: 20260266028
17+
issue: 998
18+
quality_score: 95
19+
# Version info (filled by workflow)
20+
python_version: "3.13.11"
21+
library_version: "unknown"
22+
23+
history: []

0 commit comments

Comments
 (0)