|
1 | 1 | """ anyplot.ai |
2 | 2 | errorbar-basic: Basic Error Bar Plot |
3 | | -Library: seaborn 0.13.2 | Python 3.14.4 |
4 | | -Quality: 89/100 | Updated: 2026-04-25 |
| 3 | +Library: seaborn 0.13.2 | Python 3.13.14 |
| 4 | +Quality: 88/100 | Updated: 2026-06-30 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import os |
8 | 8 |
|
| 9 | +import matplotlib.patches as mpatches |
9 | 10 | import matplotlib.pyplot as plt |
10 | 11 | import numpy as np |
11 | 12 | import pandas as pd |
|
17 | 18 | ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" |
18 | 19 | INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
19 | 20 | INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
| 21 | +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" |
20 | 22 |
|
| 23 | +# Imprint palette |
21 | 24 | IMPRINT = ["#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD", "#954477"] |
22 | 25 | BRAND = IMPRINT[0] |
23 | 26 | ACCENT = IMPRINT[1] |
24 | 27 |
|
25 | | -# Clinical trial: symptom reduction (%) measured for each treatment group |
| 28 | +# Clinical trial: symptom reduction (%) by dose group (n=30 per group) |
26 | 29 | np.random.seed(42) |
27 | | -categories = ["Control", "Treatment A", "Treatment B", "Treatment C", "Treatment D", "Treatment E"] |
28 | | -means = [45.2, 52.8, 61.3, 48.7, 57.4, 43.1] |
29 | | -stds = [4.5, 6.2, 5.8, 7.1, 4.9, 5.5] |
| 30 | +categories = ["Control", "Placebo", "10 mg", "25 mg", "50 mg", "100 mg"] |
| 31 | +means = [45.2, 46.8, 52.3, 57.4, 61.3, 58.9] |
| 32 | +stds = [4.5, 5.1, 6.2, 4.9, 5.8, 7.1] |
30 | 33 | n_per_group = 30 |
31 | 34 |
|
32 | 35 | records = [ |
33 | | - {"Treatment": cat, "Symptom Reduction (%)": value} |
| 36 | + {"Dose": cat, "Symptom Reduction (%)": value} |
34 | 37 | for cat, mu, sigma in zip(categories, means, stds, strict=True) |
35 | 38 | for value in np.random.normal(mu, sigma, n_per_group) |
36 | 39 | ] |
|
50 | 53 | "xtick.color": INK_SOFT, |
51 | 54 | "ytick.color": INK_SOFT, |
52 | 55 | "grid.color": INK, |
53 | | - "grid.alpha": 0.10, |
| 56 | + "grid.alpha": 0.15, |
54 | 57 | "legend.facecolor": ELEVATED_BG, |
55 | 58 | "legend.edgecolor": INK_SOFT, |
56 | 59 | }, |
57 | 60 | ) |
58 | 61 |
|
59 | | -fig, ax = plt.subplots(figsize=(16, 9)) |
| 62 | +fig, ax = plt.subplots(figsize=(8, 4.5), dpi=400) |
60 | 63 |
|
61 | 64 | sns.barplot( |
62 | 65 | data=df, |
63 | | - x="Treatment", |
| 66 | + x="Dose", |
64 | 67 | y="Symptom Reduction (%)", |
65 | | - hue="Treatment", |
| 68 | + hue="Dose", |
66 | 69 | palette=palette, |
67 | 70 | legend=False, |
68 | 71 | errorbar="sd", |
69 | 72 | capsize=0.25, |
70 | | - err_kws={"color": INK, "linewidth": 2.5}, |
| 73 | + err_kws={"color": INK, "linewidth": 1.5}, |
71 | 74 | edgecolor=INK_SOFT, |
72 | | - linewidth=1.0, |
| 75 | + linewidth=0.6, |
73 | 76 | ax=ax, |
74 | 77 | ) |
75 | 78 |
|
76 | | -ax.set_xlabel("Treatment Group", fontsize=20) |
77 | | -ax.set_ylabel("Symptom Reduction (%)", fontsize=20) |
78 | | -ax.set_title("errorbar-basic · seaborn · anyplot.ai", fontsize=24, fontweight="medium", color=INK) |
79 | | -ax.tick_params(axis="both", labelsize=16) |
80 | | -ax.yaxis.grid(True) |
| 79 | +ax.set_xlabel("Dose Group", fontsize=10) |
| 80 | +ax.set_ylabel("Symptom Reduction (%)", fontsize=10) |
| 81 | +ax.tick_params(axis="both", labelsize=8) |
| 82 | +ax.yaxis.grid(True, alpha=0.15, linewidth=0.8) |
81 | 83 | ax.xaxis.grid(False) |
82 | 84 | ax.set_axisbelow(True) |
83 | 85 | ax.spines["top"].set_visible(False) |
84 | 86 | ax.spines["right"].set_visible(False) |
85 | 87 |
|
86 | | -plt.tight_layout() |
87 | | -plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) |
| 88 | +# Legend explaining the two-color strategy: all groups vs. top performer |
| 89 | +brand_patch = mpatches.Patch(color=BRAND, label="Dose group") |
| 90 | +accent_patch = mpatches.Patch(color=ACCENT, label=f"Top performer ({top_performer})") |
| 91 | +ax.legend(handles=[brand_patch, accent_patch], fontsize=8, framealpha=0.9, loc="lower right") |
| 92 | + |
| 93 | +# Title and subtitle placed in figure coordinates to control vertical spacing precisely |
| 94 | +fig.text( |
| 95 | + 0.5, |
| 96 | + 0.96, |
| 97 | + "errorbar-basic · python · seaborn · anyplot.ai", |
| 98 | + ha="center", |
| 99 | + va="top", |
| 100 | + fontsize=12, |
| 101 | + fontweight="medium", |
| 102 | + color=INK, |
| 103 | +) |
| 104 | +fig.text( |
| 105 | + 0.5, |
| 106 | + 0.90, |
| 107 | + f"Bars show mean ± 1 SD — {top_performer} achieves the highest mean symptom reduction", |
| 108 | + ha="center", |
| 109 | + va="top", |
| 110 | + fontsize=9, |
| 111 | + color=INK_MUTED, |
| 112 | +) |
| 113 | + |
| 114 | +fig.subplots_adjust(top=0.81, bottom=0.13, left=0.11, right=0.97) |
| 115 | +plt.savefig(f"plot-{THEME}.png", dpi=400, facecolor=PAGE_BG) |
0 commit comments