Skip to content

Commit 257ec53

Browse files
feat(seaborn): implement subplot-mosaic (#3029)
## Implementation: `subplot-mosaic` - seaborn Implements the **seaborn** version of `subplot-mosaic`. **File:** `plots/subplot-mosaic/implementations/seaborn.py` **Parent Issue:** #3002 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20617508029)* --------- 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 532a7f9 commit 257ec53

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
""" pyplots.ai
2+
subplot-mosaic: Mosaic Subplot Layout with Varying Sizes
3+
Library: seaborn 0.13.2 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-31
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
import pandas as pd
10+
import seaborn as sns
11+
12+
13+
# Data
14+
np.random.seed(42)
15+
16+
# Time series data for main overview (Panel A - wide)
17+
dates = pd.date_range("2024-01-01", periods=100, freq="D")
18+
revenue = np.cumsum(np.random.randn(100) * 500 + 200) + 50000
19+
df_overview = pd.DataFrame({"Date": dates, "Revenue ($)": revenue})
20+
21+
# Scatter data for panel B (top right)
22+
df_scatter = pd.DataFrame(
23+
{
24+
"Marketing Spend ($K)": np.random.uniform(10, 100, 50),
25+
"Conversions": np.random.uniform(100, 1000, 50) + np.random.randn(50) * 100,
26+
}
27+
)
28+
29+
# Bar data for panel C (middle left detail)
30+
categories = ["Online", "Retail", "Partner", "Direct"]
31+
df_bar = pd.DataFrame({"Channel": categories, "Sales ($K)": [450, 320, 180, 275]})
32+
33+
# Histogram data for panel D (middle right detail)
34+
response_times = np.concatenate([np.random.normal(45, 10, 300), np.random.normal(120, 25, 100)])
35+
df_hist = pd.DataFrame({"Response Time (ms)": response_times})
36+
37+
# Line data for panel E (bottom left metric)
38+
hours = np.arange(24)
39+
cpu_usage = 30 + 20 * np.sin(hours * np.pi / 12) + np.random.randn(24) * 5
40+
df_cpu = pd.DataFrame({"Hour": hours, "CPU Usage (%)": cpu_usage})
41+
42+
# Line data for panel F (bottom center metric)
43+
memory_usage = 55 + 15 * np.sin(hours * np.pi / 10 + 2) + np.random.randn(24) * 3
44+
df_memory = pd.DataFrame({"Hour": hours, "Memory Usage (%)": memory_usage})
45+
46+
# Box data for panel G (bottom right metric)
47+
regions = ["North", "South", "East", "West"]
48+
df_box = pd.DataFrame(
49+
{
50+
"Region": np.repeat(regions, 30),
51+
"Latency (ms)": np.concatenate(
52+
[
53+
np.random.normal(25, 5, 30),
54+
np.random.normal(35, 8, 30),
55+
np.random.normal(28, 4, 30),
56+
np.random.normal(40, 10, 30),
57+
]
58+
),
59+
}
60+
)
61+
62+
# Create mosaic layout: "AAB;CCD;EFG" pattern
63+
# A spans 2 cols (wide overview), B is 1 col (scatter)
64+
# C spans 2 cols (bar chart middle), D is 1 col (histogram)
65+
# E, F, G each 1 col (three small metrics)
66+
fig, axes = plt.subplot_mosaic(
67+
[["A", "A", "B"], ["C", "C", "D"], ["E", "F", "G"]], figsize=(16, 9), height_ratios=[1.2, 1, 0.8]
68+
)
69+
70+
# Panel A: Revenue Overview (Line plot - wide)
71+
sns.lineplot(data=df_overview, x="Date", y="Revenue ($)", ax=axes["A"], color="#306998", linewidth=2.5)
72+
axes["A"].set_title("Revenue Trend Overview", fontsize=18, fontweight="bold")
73+
axes["A"].set_xlabel("Date", fontsize=14)
74+
axes["A"].set_ylabel("Revenue ($)", fontsize=14)
75+
axes["A"].tick_params(axis="both", labelsize=11)
76+
axes["A"].xaxis.set_major_locator(plt.MaxNLocator(6))
77+
axes["A"].grid(True, alpha=0.3, linestyle="--")
78+
79+
# Panel B: Marketing vs Conversions (Scatter)
80+
sns.scatterplot(
81+
data=df_scatter,
82+
x="Marketing Spend ($K)",
83+
y="Conversions",
84+
ax=axes["B"],
85+
color="#FFD43B",
86+
s=100,
87+
alpha=0.7,
88+
edgecolor="#306998",
89+
linewidth=1,
90+
)
91+
axes["B"].set_title("Marketing ROI", fontsize=16, fontweight="bold")
92+
axes["B"].set_xlabel("Marketing Spend ($K)", fontsize=13)
93+
axes["B"].set_ylabel("Conversions", fontsize=13)
94+
axes["B"].tick_params(axis="both", labelsize=10)
95+
axes["B"].grid(True, alpha=0.3, linestyle="--")
96+
97+
# Panel C: Sales by Channel (Bar - wide)
98+
sns.barplot(
99+
data=df_bar,
100+
x="Channel",
101+
y="Sales ($K)",
102+
ax=axes["C"],
103+
hue="Channel",
104+
palette=["#306998", "#FFD43B", "#4B8BBE", "#FFE873"],
105+
legend=False,
106+
)
107+
axes["C"].set_title("Sales by Channel", fontsize=16, fontweight="bold")
108+
axes["C"].set_xlabel("Channel", fontsize=13)
109+
axes["C"].set_ylabel("Sales ($K)", fontsize=13)
110+
axes["C"].tick_params(axis="both", labelsize=10)
111+
axes["C"].grid(True, axis="y", alpha=0.3, linestyle="--")
112+
113+
# Panel D: Response Time Distribution (Histogram)
114+
sns.histplot(data=df_hist, x="Response Time (ms)", ax=axes["D"], bins=30, color="#306998", alpha=0.7, edgecolor="white")
115+
axes["D"].set_title("Response Times", fontsize=16, fontweight="bold")
116+
axes["D"].set_xlabel("Response Time (ms)", fontsize=13)
117+
axes["D"].set_ylabel("Count", fontsize=13)
118+
axes["D"].tick_params(axis="both", labelsize=10)
119+
axes["D"].grid(True, axis="y", alpha=0.3, linestyle="--")
120+
121+
# Panel E: CPU Usage (Small line)
122+
sns.lineplot(data=df_cpu, x="Hour", y="CPU Usage (%)", ax=axes["E"], color="#306998", linewidth=2)
123+
axes["E"].set_title("CPU Usage", fontsize=14, fontweight="bold")
124+
axes["E"].set_xlabel("Hour", fontsize=11)
125+
axes["E"].set_ylabel("CPU (%)", fontsize=11)
126+
axes["E"].tick_params(axis="both", labelsize=9)
127+
axes["E"].set_xticks([0, 6, 12, 18, 23])
128+
axes["E"].grid(True, alpha=0.3, linestyle="--")
129+
130+
# Panel F: Memory Usage (Small line)
131+
sns.lineplot(data=df_memory, x="Hour", y="Memory Usage (%)", ax=axes["F"], color="#FFD43B", linewidth=2)
132+
axes["F"].set_title("Memory Usage", fontsize=14, fontweight="bold")
133+
axes["F"].set_xlabel("Hour", fontsize=11)
134+
axes["F"].set_ylabel("Memory (%)", fontsize=11)
135+
axes["F"].tick_params(axis="both", labelsize=9)
136+
axes["F"].set_xticks([0, 6, 12, 18, 23])
137+
axes["F"].grid(True, alpha=0.3, linestyle="--")
138+
139+
# Panel G: Latency by Region (Small box)
140+
sns.boxplot(
141+
data=df_box,
142+
x="Region",
143+
y="Latency (ms)",
144+
ax=axes["G"],
145+
hue="Region",
146+
palette=["#306998", "#FFD43B", "#4B8BBE", "#FFE873"],
147+
legend=False,
148+
)
149+
axes["G"].set_title("Latency", fontsize=14, fontweight="bold")
150+
axes["G"].set_xlabel("Region", fontsize=11)
151+
axes["G"].set_ylabel("Latency (ms)", fontsize=11)
152+
axes["G"].tick_params(axis="both", labelsize=9)
153+
axes["G"].grid(True, axis="y", alpha=0.3, linestyle="--")
154+
155+
# Main title
156+
fig.suptitle("subplot-mosaic · seaborn · pyplots.ai", fontsize=22, fontweight="bold", y=0.98)
157+
158+
plt.tight_layout(rect=[0, 0, 1, 0.95])
159+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
library: seaborn
2+
specification_id: subplot-mosaic
3+
created: '2025-12-31T10:56:16Z'
4+
updated: '2025-12-31T11:06:47Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20617508029
7+
issue: 3002
8+
python_version: 3.13.11
9+
library_version: 0.13.2
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/seaborn/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/subplot-mosaic/seaborn/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent implementation of complex mosaic layout demonstrating the ASCII-art
17+
style pattern AAB;CCD;EFG
18+
- Clear visual hierarchy with larger overview panel at top and smaller metric panels
19+
at bottom
20+
- Professional color scheme using consistent Python-themed blue/yellow palette
21+
- Good use of height_ratios to create visual emphasis on different panels
22+
- Clean, readable code following KISS principles
23+
- Realistic business dashboard scenario with appropriate data ranges
24+
- All seaborn plotting functions used correctly with modern API (hue parameter)
25+
weaknesses:
26+
- Main title font size (22pt) is slightly below the recommended 24pt for optimal
27+
legibility at 4800x2700
28+
- Could leverage more seaborn-distinctive features like regression lines, KDE overlays,
29+
or statistical annotations
30+
- Feature coverage could include additional plot types to better demonstrate mosaic
31+
flexibility

0 commit comments

Comments
 (0)