Skip to content

Commit 222fe73

Browse files
feat(matplotlib): implement marimekko-basic (#1087)
## Implementation: `marimekko-basic` - matplotlib Implements the **matplotlib** version of `marimekko-basic`. **File:** `plots/marimekko-basic/implementations/matplotlib.py` **Parent Issue:** #1002 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20280360884)* --------- 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 0b16982 commit 222fe73

2 files changed

Lines changed: 137 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""
2+
marimekko-basic: Basic Marimekko Chart
3+
Library: matplotlib
4+
"""
5+
6+
import matplotlib.pyplot as plt
7+
import numpy as np
8+
9+
10+
# Data: Market share by region (x-category) and product line (y-category)
11+
# Regions have different total market sizes (determines bar widths)
12+
# Products have different shares within each region (determines segment heights)
13+
regions = ["North America", "Europe", "Asia Pacific", "Latin America"]
14+
products = ["Electronics", "Apparel", "Home & Garden", "Sports"]
15+
16+
# Values matrix: rows = products, columns = regions
17+
# Each column total determines that region's bar width
18+
values = np.array(
19+
[
20+
[120, 85, 200, 35], # Electronics
21+
[80, 110, 150, 45], # Apparel
22+
[60, 70, 80, 25], # Home & Garden
23+
[40, 35, 70, 15], # Sports
24+
]
25+
)
26+
27+
# Colors - Python blue/yellow first, then colorblind-safe additions
28+
colors = ["#306998", "#FFD43B", "#4DAF4A", "#984EA3"]
29+
30+
# Calculate bar widths (proportional to column totals)
31+
column_totals = values.sum(axis=0)
32+
total = column_totals.sum()
33+
bar_widths = column_totals / total
34+
35+
# Calculate cumulative widths for x-positioning
36+
cum_widths = np.concatenate([[0], np.cumsum(bar_widths)[:-1]])
37+
38+
# Create figure (4800x2700 px at dpi=300)
39+
fig, ax = plt.subplots(figsize=(16, 9))
40+
41+
# Draw each segment
42+
for i, (product, color) in enumerate(zip(products, colors, strict=True)):
43+
# Calculate heights as proportion of column total
44+
heights = values[i] / column_totals
45+
46+
# Calculate bottom positions (cumulative heights of products below)
47+
bottoms = values[:i].sum(axis=0) / column_totals if i > 0 else np.zeros(len(regions))
48+
49+
# Draw bars for this product across all regions
50+
for j in range(len(regions)):
51+
ax.bar(
52+
cum_widths[j] + bar_widths[j] / 2,
53+
heights[j],
54+
width=bar_widths[j] * 0.98, # Small gap between bars
55+
bottom=bottoms[j],
56+
color=color,
57+
edgecolor="white",
58+
linewidth=2,
59+
label=product if j == 0 else None,
60+
)
61+
62+
# Add value labels on larger segments
63+
if heights[j] > 0.12:
64+
ax.text(
65+
cum_widths[j] + bar_widths[j] / 2,
66+
bottoms[j] + heights[j] / 2,
67+
f"${values[i, j]}M",
68+
ha="center",
69+
va="center",
70+
fontsize=14,
71+
fontweight="bold",
72+
color="white" if color == "#306998" else "black",
73+
)
74+
75+
# Add region labels at the bottom
76+
for j, region in enumerate(regions):
77+
ax.text(
78+
cum_widths[j] + bar_widths[j] / 2,
79+
-0.05,
80+
f"{region}\n(${column_totals[j]:.0f}M)",
81+
ha="center",
82+
va="top",
83+
fontsize=16,
84+
fontweight="bold",
85+
)
86+
87+
# Style the plot
88+
ax.set_xlim(0, 1)
89+
ax.set_ylim(-0.15, 1)
90+
ax.set_ylabel("Share within Region", fontsize=20)
91+
ax.set_title("marimekko-basic · matplotlib · pyplots.ai", fontsize=24)
92+
93+
# Format y-axis as percentage
94+
ax.set_yticks([0, 0.25, 0.5, 0.75, 1.0])
95+
ax.set_yticklabels(["0%", "25%", "50%", "75%", "100%"])
96+
ax.tick_params(axis="y", labelsize=16)
97+
98+
# Remove x-axis ticks (we have custom labels)
99+
ax.set_xticks([])
100+
101+
# Add legend
102+
ax.legend(loc="upper left", bbox_to_anchor=(1.02, 1), fontsize=16, title="Product Lines", title_fontsize=18)
103+
104+
# Subtle grid on y-axis only
105+
ax.yaxis.grid(True, alpha=0.3, linestyle="--")
106+
ax.set_axisbelow(True)
107+
108+
# Remove top and right spines
109+
ax.spines["top"].set_visible(False)
110+
ax.spines["right"].set_visible(False)
111+
ax.spines["bottom"].set_visible(False)
112+
113+
plt.tight_layout()
114+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Per-library metadata for matplotlib implementation of marimekko-basic
2+
# Auto-generated by impl-generate.yml
3+
4+
library: matplotlib
5+
specification_id: marimekko-basic
6+
7+
# Preview URLs (filled by workflow)
8+
preview_url: https://storage.googleapis.com/pyplots-images/plots/marimekko-basic/matplotlib/plot.png
9+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/marimekko-basic/matplotlib/plot_thumb.png
10+
preview_html: null
11+
12+
current:
13+
version: 0
14+
generated_at: 2025-12-16T19:40:17Z
15+
generated_by: claude-opus-4-5-20251101
16+
workflow_run: 20280360884
17+
issue: 1002
18+
quality_score: 94
19+
# Version info (filled by workflow)
20+
python_version: "3.13.11"
21+
library_version: "unknown"
22+
23+
history: []

0 commit comments

Comments
 (0)