|
1 | 1 | """ anyplot.ai |
2 | 2 | ecdf-basic: Basic ECDF Plot |
3 | | -Library: seaborn 0.13.2 | Python 3.14.4 |
4 | | -Quality: 88/100 | Updated: 2026-04-24 |
| 3 | +Library: seaborn 0.13.2 | Python 3.13.14 |
| 4 | +Quality: 90/100 | Updated: 2026-06-25 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import os |
|
10 | 10 | import seaborn as sns |
11 | 11 |
|
12 | 12 |
|
13 | | -# Theme tokens |
| 13 | +# Theme tokens — Imprint palette + theme-adaptive chrome |
14 | 14 | THEME = os.getenv("ANYPLOT_THEME", "light") |
15 | 15 | PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" |
16 | 16 | ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" |
17 | 17 | INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
18 | 18 | INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
19 | | -BRAND = "#009E73" # Okabe-Ito position 1 |
| 19 | +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" |
| 20 | + |
| 21 | +# Imprint categorical palette — positions 1, 2, 3 (Adelie, Chinstrap, Gentoo) |
| 22 | +IMPRINT_PALETTE = ["#009E73", "#C475FD", "#4467A3"] |
20 | 23 |
|
21 | 24 | sns.set_theme( |
22 | 25 | style="ticks", |
|
29 | 32 | "xtick.color": INK_SOFT, |
30 | 33 | "ytick.color": INK_SOFT, |
31 | 34 | "grid.color": INK, |
32 | | - "grid.alpha": 0.10, |
| 35 | + "grid.alpha": 0.12, |
33 | 36 | "legend.facecolor": ELEVATED_BG, |
34 | 37 | "legend.edgecolor": INK_SOFT, |
35 | 38 | }, |
36 | 39 | ) |
37 | 40 |
|
38 | | -# Data - real-world sample: penguin flipper lengths |
39 | | -penguins = sns.load_dataset("penguins").dropna(subset=["flipper_length_mm"]) |
| 41 | +# Data — penguin flipper lengths by species (deterministic real-world dataset) |
| 42 | +penguins = sns.load_dataset("penguins").dropna(subset=["flipper_length_mm", "species"]) |
40 | 43 |
|
41 | | -# Plot |
42 | | -fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG) |
| 44 | +# Plot — multi-hue ecdfplot shows distribution comparison across species |
| 45 | +fig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG) |
43 | 46 | ax.set_facecolor(PAGE_BG) |
44 | 47 |
|
45 | | -sns.ecdfplot(data=penguins, x="flipper_length_mm", ax=ax, linewidth=3.5, color=BRAND) |
| 48 | +sns.ecdfplot(data=penguins, x="flipper_length_mm", hue="species", palette=IMPRINT_PALETTE, linewidth=2.5, ax=ax) |
| 49 | + |
| 50 | +# Percentile reference lines for direct reading of Q1 / median / Q3 |
| 51 | +for p in (0.25, 0.50, 0.75): |
| 52 | + ax.axhline(p, color=INK_MUTED, linewidth=0.7, linestyle="--", alpha=0.55, zorder=0) |
46 | 53 |
|
47 | 54 | # Style |
48 | | -ax.set_xlabel("Flipper Length (mm)", fontsize=20, color=INK) |
49 | | -ax.set_ylabel("Cumulative Proportion", fontsize=20, color=INK) |
50 | | -ax.set_title("Penguin Flipper Lengths · ecdf-basic · seaborn · anyplot.ai", fontsize=24, fontweight="medium", color=INK) |
51 | | -ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT) |
| 55 | +title = "Penguin Flipper Lengths · ecdf-basic · python · seaborn · anyplot.ai" |
| 56 | +n = len(title) |
| 57 | +title_fontsize = round(12 * 67 / n) if n > 67 else 12 |
| 58 | +ax.set_title(title, fontsize=title_fontsize, fontweight="medium", color=INK) |
| 59 | +ax.set_xlabel("Flipper Length (mm)", fontsize=10, color=INK) |
| 60 | +ax.set_ylabel("Cumulative Proportion", fontsize=10, color=INK) |
| 61 | +ax.tick_params(axis="both", labelsize=8, colors=INK_SOFT) |
52 | 62 | ax.set_ylim(0, 1) |
| 63 | +ax.set_yticks([0, 0.25, 0.50, 0.75, 1.0]) |
53 | 64 |
|
54 | 65 | ax.spines["top"].set_visible(False) |
55 | 66 | ax.spines["right"].set_visible(False) |
56 | 67 | for side in ("left", "bottom"): |
57 | 68 | ax.spines[side].set_color(INK_SOFT) |
58 | 69 |
|
59 | | -ax.grid(True, axis="both", alpha=0.10, linewidth=0.8, color=INK) |
| 70 | +ax.yaxis.grid(True, alpha=0.12, linewidth=0.8, color=INK) |
60 | 71 | ax.set_axisbelow(True) |
61 | 72 |
|
62 | | -plt.tight_layout() |
63 | | -plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) |
| 73 | +# Style the auto-generated legend |
| 74 | +legend = ax.get_legend() |
| 75 | +if legend: |
| 76 | + legend.get_frame().set_facecolor(ELEVATED_BG) |
| 77 | + legend.get_frame().set_edgecolor(INK_SOFT) |
| 78 | + for text in legend.get_texts(): |
| 79 | + text.set_color(INK_SOFT) |
| 80 | + text.set_fontsize(8) |
| 81 | + legend.set_title("Species", prop={"size": 8, "weight": "medium"}) |
| 82 | + legend.get_title().set_color(INK_SOFT) |
| 83 | + |
| 84 | +# Save — bbox_inches must stay default (None) to preserve exact figsize × dpi canvas |
| 85 | +plt.savefig(f"plot-{THEME}.png", dpi=400, facecolor=PAGE_BG) |
0 commit comments