|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | scatter-marginal: Scatter Plot with Marginal Distributions |
3 | | -Library: matplotlib 3.10.8 | Python 3.13.11 |
4 | | -Quality: 91/100 | Created: 2025-12-26 |
| 3 | +Library: matplotlib 3.10.9 | Python 3.13.13 |
| 4 | +Quality: 89/100 | Updated: 2026-05-09 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import matplotlib.pyplot as plt |
8 | 10 | import numpy as np |
9 | 11 | from matplotlib.gridspec import GridSpec |
10 | 12 |
|
11 | 13 |
|
| 14 | +# Theme tokens |
| 15 | +THEME = os.getenv("ANYPLOT_THEME", "light") |
| 16 | +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" |
| 17 | +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
| 18 | +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
| 19 | +BRAND = "#009E73" |
| 20 | + |
12 | 21 | # Data - correlated bivariate data with realistic pattern |
13 | 22 | np.random.seed(42) |
14 | 23 | n = 200 |
15 | 24 |
|
16 | | -# Create correlated data with some structure |
17 | | -x = np.concatenate( |
18 | | - [ |
19 | | - np.random.normal(30, 8, n // 2), # First cluster |
20 | | - np.random.normal(60, 10, n // 2), # Second cluster |
21 | | - ] |
22 | | -) |
23 | | -y = 0.7 * x + np.random.normal(0, 8, n) + 10 # Linear relationship with noise |
| 25 | +# Create correlated data with bimodal structure |
| 26 | +x = np.concatenate([np.random.normal(30, 8, n // 2), np.random.normal(60, 10, n // 2)]) |
| 27 | +y = 0.7 * x + np.random.normal(0, 8, n) + 10 |
24 | 28 |
|
25 | 29 | # Create figure with GridSpec for layout |
26 | | -fig = plt.figure(figsize=(16, 9)) |
| 30 | +fig = plt.figure(figsize=(16, 9), facecolor=PAGE_BG) |
27 | 31 | gs = GridSpec(4, 4, figure=fig, hspace=0.05, wspace=0.05) |
28 | 32 |
|
29 | 33 | # Main scatter plot (lower-left, 3x3) |
30 | | -ax_main = fig.add_subplot(gs[1:4, 0:3]) |
31 | | -ax_main.scatter(x, y, s=120, alpha=0.65, color="#306998", edgecolors="white", linewidth=0.5) |
32 | | -ax_main.set_xlabel("X Value", fontsize=20) |
33 | | -ax_main.set_ylabel("Y Value", fontsize=20) |
34 | | -ax_main.tick_params(axis="both", labelsize=16) |
35 | | -ax_main.grid(True, alpha=0.3, linestyle="--") |
| 34 | +ax_main = fig.add_subplot(gs[1:4, 0:3], facecolor=PAGE_BG) |
| 35 | +ax_main.scatter(x, y, s=100, alpha=0.65, color=BRAND, edgecolors=PAGE_BG, linewidth=0.5) |
| 36 | +ax_main.set_xlabel("Feature A", fontsize=20, color=INK) |
| 37 | +ax_main.set_ylabel("Feature B", fontsize=20, color=INK) |
| 38 | +ax_main.tick_params(axis="both", labelsize=16, colors=INK_SOFT) |
| 39 | +ax_main.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK) |
| 40 | +for s in ("left", "bottom"): |
| 41 | + ax_main.spines[s].set_color(INK_SOFT) |
| 42 | +ax_main.spines["top"].set_visible(False) |
| 43 | +ax_main.spines["right"].set_visible(False) |
36 | 44 |
|
37 | 45 | # Top marginal histogram (aligned with main x-axis) |
38 | | -ax_top = fig.add_subplot(gs[0, 0:3], sharex=ax_main) |
39 | | -ax_top.hist(x, bins=25, color="#306998", alpha=0.7, edgecolor="white", linewidth=0.8) |
40 | | -ax_top.tick_params(axis="x", labelbottom=False) |
41 | | -ax_top.tick_params(axis="y", labelsize=14) |
42 | | -ax_top.set_ylabel("Count", fontsize=16) |
| 46 | +ax_top = fig.add_subplot(gs[0, 0:3], sharex=ax_main, facecolor=PAGE_BG) |
| 47 | +ax_top.hist(x, bins=25, color=BRAND, alpha=0.5, edgecolor=PAGE_BG, linewidth=0.5) |
| 48 | +ax_top.tick_params(axis="x", labelbottom=False, colors=INK_SOFT) |
| 49 | +ax_top.tick_params(axis="y", labelsize=14, colors=INK_SOFT) |
| 50 | +ax_top.set_ylabel("Count", fontsize=16, color=INK) |
43 | 51 | ax_top.spines["top"].set_visible(False) |
44 | 52 | ax_top.spines["right"].set_visible(False) |
| 53 | +for s in ("left", "bottom"): |
| 54 | + ax_top.spines[s].set_color(INK_SOFT) |
| 55 | +ax_top.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK) |
45 | 56 |
|
46 | 57 | # Right marginal histogram (aligned with main y-axis) |
47 | | -ax_right = fig.add_subplot(gs[1:4, 3], sharey=ax_main) |
48 | | -ax_right.hist(y, bins=25, orientation="horizontal", color="#306998", alpha=0.7, edgecolor="white", linewidth=0.8) |
49 | | -ax_right.tick_params(axis="y", labelleft=False) |
50 | | -ax_right.tick_params(axis="x", labelsize=14) |
51 | | -ax_right.set_xlabel("Count", fontsize=16) |
| 58 | +ax_right = fig.add_subplot(gs[1:4, 3], sharey=ax_main, facecolor=PAGE_BG) |
| 59 | +ax_right.hist(y, bins=25, orientation="horizontal", color=BRAND, alpha=0.5, edgecolor=PAGE_BG, linewidth=0.5) |
| 60 | +ax_right.tick_params(axis="y", labelleft=False, colors=INK_SOFT) |
| 61 | +ax_right.tick_params(axis="x", labelsize=14, colors=INK_SOFT) |
| 62 | +ax_right.set_xlabel("Count", fontsize=16, color=INK) |
52 | 63 | ax_right.spines["top"].set_visible(False) |
53 | 64 | ax_right.spines["right"].set_visible(False) |
| 65 | +for s in ("left", "bottom"): |
| 66 | + ax_right.spines[s].set_color(INK_SOFT) |
| 67 | +ax_right.xaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK) |
54 | 68 |
|
55 | | -# Title in the top-right corner area |
| 69 | +# Title |
56 | 70 | fig.text( |
57 | | - 0.98, 0.98, "scatter-marginal · matplotlib · pyplots.ai", fontsize=24, ha="right", va="top", fontweight="normal" |
| 71 | + 0.5, |
| 72 | + 0.98, |
| 73 | + "scatter-marginal · matplotlib · anyplot.ai", |
| 74 | + fontsize=24, |
| 75 | + ha="center", |
| 76 | + va="top", |
| 77 | + color=INK, |
| 78 | + fontweight="medium", |
58 | 79 | ) |
59 | 80 |
|
60 | | -plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor="white") |
| 81 | +plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) |
0 commit comments