Skip to content

Commit 2874980

Browse files
feat(plotly): implement subplot-grid (#2823)
## Implementation: `subplot-grid` - plotly Implements the **plotly** version of `subplot-grid`. **File:** `plots/subplot-grid/implementations/plotly.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20602446641)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent ef2c4ee commit 2874980

2 files changed

Lines changed: 151 additions & 0 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
""" pyplots.ai
2+
subplot-grid: Subplot Grid Layout
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-30
5+
"""
6+
7+
import numpy as np
8+
import pandas as pd
9+
import plotly.graph_objects as go
10+
from plotly.subplots import make_subplots
11+
12+
13+
# Data - Financial dashboard example
14+
np.random.seed(42)
15+
16+
# Generate 60 days of stock data
17+
days = 60
18+
dates = pd.date_range("2024-01-01", periods=days, freq="D")
19+
20+
# Stock price with realistic walk
21+
returns = np.random.normal(0.001, 0.02, days)
22+
price = 100 * np.cumprod(1 + returns)
23+
24+
# Volume data (correlated with absolute price movement)
25+
base_volume = 1000000
26+
volume = base_volume + np.abs(returns) * 50000000 + np.random.normal(0, 200000, days)
27+
volume = np.clip(volume, 500000, 3000000)
28+
29+
# Daily returns for histogram
30+
daily_returns = np.diff(price) / price[:-1] * 100
31+
32+
# Moving averages
33+
ma_20 = pd.Series(price).rolling(20).mean().values
34+
35+
# Create 2x2 subplot grid
36+
fig = make_subplots(
37+
rows=2,
38+
cols=2,
39+
subplot_titles=("Stock Price & Moving Average", "Trading Volume", "Daily Returns Distribution", "Price vs Volume"),
40+
horizontal_spacing=0.1,
41+
vertical_spacing=0.12,
42+
specs=[[{"type": "scatter"}, {"type": "bar"}], [{"type": "histogram"}, {"type": "scatter"}]],
43+
)
44+
45+
# Colors
46+
python_blue = "#306998"
47+
python_yellow = "#FFD43B"
48+
accent_green = "#2E7D32"
49+
accent_red = "#C62828"
50+
51+
# Subplot 1: Line chart - Stock price with moving average
52+
fig.add_trace(
53+
go.Scatter(x=dates, y=price, mode="lines", name="Price", line={"color": python_blue, "width": 3}), row=1, col=1
54+
)
55+
fig.add_trace(
56+
go.Scatter(
57+
x=dates, y=ma_20, mode="lines", name="20-day MA", line={"color": python_yellow, "width": 2, "dash": "dash"}
58+
),
59+
row=1,
60+
col=1,
61+
)
62+
63+
# Subplot 2: Bar chart - Volume
64+
volume_colors = [accent_green if r >= 0 else accent_red for r in returns]
65+
fig.add_trace(go.Bar(x=dates, y=volume, name="Volume", marker={"color": volume_colors, "opacity": 0.7}), row=1, col=2)
66+
67+
# Subplot 3: Histogram - Daily returns distribution
68+
fig.add_trace(
69+
go.Histogram(
70+
x=daily_returns,
71+
nbinsx=20,
72+
name="Returns",
73+
marker={"color": python_blue, "opacity": 0.7, "line": {"color": "white", "width": 1}},
74+
),
75+
row=2,
76+
col=1,
77+
)
78+
79+
# Subplot 4: Scatter - Price vs Volume relationship
80+
fig.add_trace(
81+
go.Scatter(
82+
x=volume,
83+
y=price,
84+
mode="markers",
85+
name="Price-Volume",
86+
marker={"color": python_blue, "size": 10, "opacity": 0.6, "line": {"color": "white", "width": 1}},
87+
),
88+
row=2,
89+
col=2,
90+
)
91+
92+
# Update layout
93+
fig.update_layout(
94+
title={"text": "subplot-grid \u00b7 plotly \u00b7 pyplots.ai", "font": {"size": 32}, "x": 0.5, "xanchor": "center"},
95+
showlegend=True,
96+
legend={"font": {"size": 16}, "x": 1.02, "y": 1, "xanchor": "left", "yanchor": "top"},
97+
template="plotly_white",
98+
margin={"l": 80, "r": 150, "t": 120, "b": 80},
99+
)
100+
101+
# Update all axes fonts
102+
fig.update_xaxes(tickfont={"size": 14}, title_font={"size": 18})
103+
fig.update_yaxes(tickfont={"size": 14}, title_font={"size": 18})
104+
105+
# Specific axis labels
106+
fig.update_xaxes(title_text="Date", row=1, col=1)
107+
fig.update_yaxes(title_text="Price ($)", row=1, col=1)
108+
fig.update_xaxes(title_text="Date", row=1, col=2)
109+
fig.update_yaxes(title_text="Volume", row=1, col=2)
110+
fig.update_xaxes(title_text="Daily Return (%)", row=2, col=1)
111+
fig.update_yaxes(title_text="Frequency", row=2, col=1)
112+
fig.update_xaxes(title_text="Volume", row=2, col=2)
113+
fig.update_yaxes(title_text="Price ($)", row=2, col=2)
114+
115+
# Update subplot titles font size
116+
for annotation in fig["layout"]["annotations"]:
117+
annotation["font"] = {"size": 20}
118+
119+
# Save as PNG (4800x2700 via scale=3)
120+
fig.write_image("plot.png", width=1600, height=900, scale=3)
121+
122+
# Save interactive HTML
123+
fig.write_html("plot.html", include_plotlyjs=True)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library: plotly
2+
specification_id: subplot-grid
3+
created: '2025-12-30T17:49:58Z'
4+
updated: '2025-12-30T18:01:57Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20602446641
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/subplot-grid/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/subplot-grid/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/subplot-grid/plotly/plot.html
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent demonstration of Plotly's make_subplots capability with different chart
17+
types in each cell
18+
- Well-chosen financial dashboard scenario that naturally requires multiple visualization
19+
types
20+
- Clean color scheme using Python blue (#306998) and yellow (#FFD43B) consistently
21+
- Proper use of specs parameter to define chart types per cell
22+
- Good axis labeling with units throughout
23+
- Interactive HTML export alongside static PNG
24+
weaknesses:
25+
- Missing grid lines would improve readability of individual subplots (add gridcolor
26+
and showgrid to axes)
27+
- Scatter markers in bottom-right subplot could be slightly larger (12-14 instead
28+
of 10) for better visibility

0 commit comments

Comments
 (0)