Skip to content

Commit 4839262

Browse files
feat(matplotlib): implement subplot-grid-custom (#2884)
## Implementation: `subplot-grid-custom` - matplotlib Implements the **matplotlib** version of `subplot-grid-custom`. **File:** `plots/subplot-grid-custom/implementations/matplotlib.py` **Parent Issue:** #2856 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20608469966)* --------- 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 10aeb52 commit 4839262

2 files changed

Lines changed: 150 additions & 0 deletions

File tree

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
""" pyplots.ai
2+
subplot-grid-custom: Custom Subplot Grid Layout
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-30
5+
"""
6+
7+
import matplotlib.dates as mdates
8+
import matplotlib.gridspec as gridspec
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
import pandas as pd
12+
13+
14+
# Data
15+
np.random.seed(42)
16+
17+
# Time series data for main plot (spanning 2 columns)
18+
dates = pd.date_range("2024-01-01", periods=120, freq="D")
19+
base_price = 100
20+
returns = np.random.randn(120) * 0.02
21+
prices = base_price * np.cumprod(1 + returns)
22+
23+
# Volume data for bar chart
24+
volume = np.random.uniform(1e6, 5e6, 120)
25+
26+
# Returns distribution for histogram
27+
daily_returns = np.diff(prices) / prices[:-1] * 100
28+
29+
# Scatter data for correlation plot
30+
x_corr = np.random.randn(50) * 10 + 50
31+
y_corr = x_corr * 0.7 + np.random.randn(50) * 5
32+
33+
# Category data for bar chart
34+
categories = ["A", "B", "C", "D"]
35+
values = [85, 72, 93, 67]
36+
37+
# Create figure with GridSpec (custom layout)
38+
fig = plt.figure(figsize=(16, 9))
39+
gs = gridspec.GridSpec(3, 3, figure=fig, height_ratios=[2, 1, 1], wspace=0.35, hspace=0.5)
40+
41+
# Main plot: Time series spanning 2 columns and 2 rows (top-left)
42+
ax_main = fig.add_subplot(gs[0:2, 0:2])
43+
ax_main.plot(dates, prices, color="#306998", linewidth=2.5, label="Price")
44+
ax_main.fill_between(dates, prices.min() * 0.95, prices, alpha=0.2, color="#306998")
45+
ax_main.set_xlabel("Date", fontsize=18)
46+
ax_main.set_ylabel("Price ($)", fontsize=18)
47+
ax_main.set_title("Price Trend (Main View)", fontsize=20, fontweight="bold")
48+
ax_main.tick_params(axis="both", labelsize=14)
49+
ax_main.grid(True, alpha=0.3, linestyle="--")
50+
ax_main.legend(fontsize=14, loc="upper left")
51+
# Format date labels to avoid overlap
52+
ax_main.xaxis.set_major_locator(mdates.MonthLocator())
53+
ax_main.xaxis.set_major_formatter(mdates.DateFormatter("%b"))
54+
55+
# Top right: Correlation scatter plot
56+
ax_scatter = fig.add_subplot(gs[0, 2])
57+
ax_scatter.scatter(x_corr, y_corr, s=150, alpha=0.7, color="#FFD43B", edgecolor="#306998", linewidth=1.5)
58+
ax_scatter.set_xlabel("Variable X", fontsize=16)
59+
ax_scatter.set_ylabel("Variable Y", fontsize=16)
60+
ax_scatter.set_title("Correlation", fontsize=18, fontweight="bold")
61+
ax_scatter.tick_params(axis="both", labelsize=12)
62+
ax_scatter.grid(True, alpha=0.3, linestyle="--")
63+
64+
# Middle right: Category bar chart
65+
ax_bar = fig.add_subplot(gs[1, 2])
66+
bars = ax_bar.bar(
67+
categories, values, color=["#306998", "#FFD43B", "#306998", "#FFD43B"], edgecolor="white", linewidth=2
68+
)
69+
ax_bar.set_xlabel("Product", fontsize=16)
70+
ax_bar.set_ylabel("Score", fontsize=16)
71+
ax_bar.set_title("Performance", fontsize=18, fontweight="bold")
72+
ax_bar.tick_params(axis="both", labelsize=12)
73+
ax_bar.set_ylim(0, 110)
74+
for bar, val in zip(bars, values, strict=True):
75+
ax_bar.text(bar.get_x() + bar.get_width() / 2, val + 3, str(val), ha="center", fontsize=12, fontweight="bold")
76+
77+
# Bottom left: Volume bar chart
78+
ax_volume = fig.add_subplot(gs[2, 0])
79+
ax_volume.bar(range(len(volume)), volume / 1e6, color="#306998", alpha=0.7, width=1.0)
80+
ax_volume.set_xlabel("Days", fontsize=16)
81+
ax_volume.set_ylabel("Volume (M)", fontsize=16)
82+
ax_volume.set_title("Daily Volume", fontsize=18, fontweight="bold")
83+
ax_volume.tick_params(axis="both", labelsize=12)
84+
ax_volume.set_xlim(0, len(volume))
85+
86+
# Bottom middle: Returns histogram
87+
ax_hist = fig.add_subplot(gs[2, 1])
88+
ax_hist.hist(daily_returns, bins=25, color="#FFD43B", edgecolor="#306998", linewidth=1.5, alpha=0.8)
89+
ax_hist.axvline(0, color="#306998", linestyle="--", linewidth=2)
90+
ax_hist.set_xlabel("Daily Return (%)", fontsize=16)
91+
ax_hist.set_ylabel("Frequency", fontsize=16)
92+
ax_hist.set_title("Return Distribution", fontsize=18, fontweight="bold")
93+
ax_hist.tick_params(axis="both", labelsize=12)
94+
95+
# Bottom right: Summary statistics text box
96+
ax_stats = fig.add_subplot(gs[2, 2])
97+
ax_stats.axis("off")
98+
stats_text = (
99+
f"Start Price: ${base_price:.2f}\n"
100+
f"End Price: ${prices[-1]:.2f}\n"
101+
f"Total Return: {(prices[-1] / base_price - 1) * 100:.1f}%\n"
102+
f"Avg Daily Vol: {np.mean(volume) / 1e6:.1f}M\n"
103+
f"Volatility: {np.std(daily_returns):.2f}%"
104+
)
105+
ax_stats.text(
106+
0.5,
107+
0.45,
108+
stats_text,
109+
transform=ax_stats.transAxes,
110+
fontsize=15,
111+
verticalalignment="center",
112+
horizontalalignment="center",
113+
bbox={"boxstyle": "round,pad=0.6", "facecolor": "#306998", "alpha": 0.1, "edgecolor": "#306998", "linewidth": 2},
114+
family="monospace",
115+
linespacing=1.8,
116+
)
117+
ax_stats.set_title("Summary Stats", fontsize=18, fontweight="bold")
118+
119+
# Overall title
120+
fig.suptitle("subplot-grid-custom · matplotlib · pyplots.ai", fontsize=24, fontweight="bold", y=0.99)
121+
122+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library: matplotlib
2+
specification_id: subplot-grid-custom
3+
created: '2025-12-30T23:55:41Z'
4+
updated: '2025-12-31T00:01:42Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20608469966
7+
issue: 2856
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/subplot-grid-custom/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/subplot-grid-custom/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent GridSpec layout with main panel spanning 2 rows and 2 columns, demonstrating
17+
the core spec feature
18+
- Professional financial dashboard aesthetic with consistent color scheme (Python
19+
blue/yellow)
20+
- 'Good use of matplotlib-specific features: GridSpec with height_ratios, fill_between,
21+
mdates formatting'
22+
- All text is clearly legible with appropriate font sizes
23+
- Realistic financial data scenario with time series, volume, returns distribution,
24+
and summary statistics
25+
weaknesses:
26+
- Bottom row subplots appear slightly cramped compared to the main panel proportions
27+
- Library features score could be improved by using shared axes between related
28+
plots (e.g., dates) or constrained_layout

0 commit comments

Comments
 (0)