Skip to content

Commit d585d56

Browse files
feat(matplotlib): implement bar-stacked (#6133)
## Implementation: `bar-stacked` - python/matplotlib Implements the **python/matplotlib** version of `bar-stacked`. **File:** `plots/bar-stacked/implementations/python/matplotlib.py` **Parent Issue:** #1947 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25594650753)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent c69fdb0 commit d585d56

2 files changed

Lines changed: 209 additions & 162 deletions

File tree

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,79 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
bar-stacked: Stacked Bar Chart
3-
Library: matplotlib 3.10.8 | Python 3.13.11
4-
Quality: 94/100 | Created: 2025-12-26
3+
Library: matplotlib 3.10.9 | Python 3.13.13
4+
Quality: 90/100 | Updated: 2026-05-09
55
"""
66

7+
import os
8+
79
import matplotlib.pyplot as plt
810
import numpy as np
911

1012

11-
# Seed for reproducibility (data is deterministic but seed documents intent)
12-
np.random.seed(42)
13+
# Theme tokens
14+
THEME = os.getenv("ANYPLOT_THEME", "light")
15+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
16+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
17+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
18+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
19+
20+
# Okabe-Ito palette (positions 1-4)
21+
OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7"]
1322

1423
# Data: Quarterly revenue by product category (in millions USD)
1524
categories = ["Q1", "Q2", "Q3", "Q4"]
1625
products = ["Software", "Hardware", "Services", "Support"]
1726

18-
# Revenue data showing realistic business patterns
19-
software = np.array([45, 52, 48, 68]) # Growing, spike in Q4
20-
hardware = np.array([32, 28, 35, 42]) # Variable with Q4 boost
21-
services = np.array([28, 31, 38, 35]) # Steady growth
22-
support = np.array([15, 18, 20, 22]) # Consistent increase
23-
24-
# Colors: Python blue primary, then colorblind-safe palette
25-
colors = ["#306998", "#FFD43B", "#4ECDC4", "#FF6B6B"]
27+
software = np.array([45, 52, 48, 68])
28+
hardware = np.array([32, 28, 35, 42])
29+
services = np.array([28, 31, 38, 35])
30+
support = np.array([15, 18, 20, 22])
2631

27-
# Create figure (4800 x 2700 px at 300 dpi = 16 x 9 inches)
28-
fig, ax = plt.subplots(figsize=(16, 9))
32+
# Plot
33+
fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)
34+
ax.set_facecolor(PAGE_BG)
2935

30-
# Calculate bar positions
3136
x = np.arange(len(categories))
3237
bar_width = 0.6
3338

3439
# Create stacked bars
3540
bottom = np.zeros(len(categories))
3641
for i, (product, values) in enumerate(zip(products, [software, hardware, services, support], strict=True)):
37-
ax.bar(x, values, bar_width, label=product, bottom=bottom, color=colors[i], edgecolor="white", linewidth=1.5)
42+
ax.bar(x, values, bar_width, label=product, bottom=bottom, color=OKABE_ITO[i], edgecolor=PAGE_BG, linewidth=1.5)
3843
bottom += values
3944

4045
# Add total labels above each stacked bar
4146
totals = software + hardware + services + support
4247
for i, total in enumerate(totals):
43-
ax.text(i, total + 3, f"${total}M", ha="center", va="bottom", fontsize=18, fontweight="bold", color="#333333")
48+
ax.text(i, total + 3, f"${total}M", ha="center", va="bottom", fontsize=18, fontweight="bold", color=INK)
4449

45-
# Styling
46-
ax.set_xlabel("Quarter", fontsize=20)
47-
ax.set_ylabel("Revenue (Millions USD)", fontsize=20)
48-
ax.set_title("bar-stacked · matplotlib · pyplots.ai", fontsize=24)
50+
# Style
51+
ax.set_xlabel("Quarter", fontsize=20, color=INK)
52+
ax.set_ylabel("Revenue (Millions USD)", fontsize=20, color=INK)
53+
ax.set_title("bar-stacked · matplotlib · anyplot.ai", fontsize=24, fontweight="medium", color=INK)
4954
ax.set_xticks(x)
5055
ax.set_xticklabels(categories)
51-
ax.tick_params(axis="both", labelsize=16)
56+
ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT, labelcolor=INK_SOFT)
5257

53-
# Legend (outside plot area to avoid overlap with data)
54-
ax.legend(fontsize=16, loc="upper left", bbox_to_anchor=(1.02, 1), framealpha=0.95)
58+
# Legend
59+
leg = ax.legend(fontsize=16, loc="upper left", bbox_to_anchor=(1.02, 1))
60+
if leg:
61+
leg.get_frame().set_facecolor(ELEVATED_BG)
62+
leg.get_frame().set_edgecolor(INK_SOFT)
63+
plt.setp(leg.get_texts(), color=INK_SOFT)
5564

56-
# Grid (subtle, horizontal only for bar charts)
57-
ax.yaxis.grid(True, alpha=0.3, linestyle="--")
65+
# Grid (subtle, y-axis only)
66+
ax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)
5867
ax.set_axisbelow(True)
5968

60-
# Clean up spines
69+
# Spines
6170
ax.spines["top"].set_visible(False)
6271
ax.spines["right"].set_visible(False)
72+
for s in ("left", "bottom"):
73+
ax.spines[s].set_color(INK_SOFT)
6374

64-
# Set y-axis to start at 0 and add headroom for labels
75+
# Y-axis limits with headroom for labels
6576
ax.set_ylim(0, max(totals) + 20)
6677

6778
plt.tight_layout()
68-
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
79+
plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG)

0 commit comments

Comments
 (0)