Skip to content

Commit 4a05496

Browse files
update(violin-basic): seaborn — comprehensive quality review (#4323)
## Summary Updated **seaborn** implementation for **violin-basic**. **Changes:** Comprehensive quality review improving code quality, data choice, visual design, spec compliance, and library feature usage. ### Changes - Improved data generation with distinct distribution shapes per category - Enhanced visual design (explicit font sizes, refined color palette, layout balance) - Fixed review weaknesses from previous evaluation - Updated metadata with current library/Python versions - Preview images uploaded to GCS staging ## Test Plan - [x] Preview images uploaded to GCS staging - [x] Implementation file passes ruff format/check - [x] Metadata YAML updated with current versions - [ ] Automated review triggered --- Generated with [Claude Code](https://claude.com/claude-code) `/update` command --------- 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 869aa7d commit 4a05496

2 files changed

Lines changed: 220 additions & 146 deletions

File tree

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" pyplots.ai
22
violin-basic: Basic Violin Plot
3-
Library: seaborn 0.13.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: seaborn 0.13.2 | Python 3.14.3
4+
Quality: 92/100 | Updated: 2026-02-21
55
"""
66

77
import matplotlib.pyplot as plt
@@ -12,50 +12,103 @@
1212

1313
# Data - Salary distributions across departments
1414
np.random.seed(42)
15-
categories = ["Engineering", "Marketing", "Sales", "Support"]
16-
data = []
17-
18-
for cat in categories:
19-
# Different distribution shapes per category
20-
if cat == "Engineering":
21-
values = np.random.normal(85000, 15000, 150)
22-
elif cat == "Marketing":
23-
values = np.random.normal(70000, 12000, 150)
24-
elif cat == "Sales":
25-
# Bimodal distribution for sales (junior vs senior)
26-
values = np.concatenate([np.random.normal(55000, 8000, 75), np.random.normal(90000, 10000, 75)])
27-
else: # Support
28-
values = np.random.normal(55000, 10000, 150)
29-
30-
for v in values:
31-
data.append({"Department": cat, "Salary": v})
32-
33-
df = pd.DataFrame(data)
34-
35-
# Plot
15+
departments = ["Engineering", "Marketing", "Sales", "Support"]
16+
records = []
17+
18+
for dept in departments:
19+
if dept == "Engineering":
20+
salaries = np.random.normal(85000, 15000, 150)
21+
elif dept == "Marketing":
22+
salaries = np.random.normal(70000, 12000, 150)
23+
elif dept == "Sales":
24+
# Bimodal distribution (junior vs senior) — showcases KDE strength
25+
salaries = np.concatenate([np.random.normal(55000, 8000, 75), np.random.normal(90000, 10000, 75)])
26+
else:
27+
salaries = np.random.normal(55000, 10000, 150)
28+
for s in salaries:
29+
records.append({"Department": dept, "Salary": s})
30+
31+
df = pd.DataFrame(records)
32+
33+
# Distinctive palette with good contrast between categories
34+
palette = ["#306998", "#E8825A", "#5BA38B", "#C46BAE"]
35+
3636
fig, ax = plt.subplots(figsize=(16, 9))
37+
fig.patch.set_facecolor("#FAFAFA")
38+
ax.set_facecolor("#FAFAFA")
3739

40+
# Violin plot
3841
sns.violinplot(
3942
data=df,
4043
x="Department",
4144
y="Salary",
4245
hue="Department",
43-
palette=["#306998", "#FFD43B", "#306998", "#FFD43B"],
44-
inner="quart", # Show quartiles inside violin
45-
linewidth=2,
46+
palette=palette,
47+
inner="box",
48+
cut=0,
49+
linewidth=1.2,
50+
saturation=0.85,
51+
legend=False,
52+
ax=ax,
53+
)
54+
55+
# Stripplot overlay — signature seaborn layering pattern
56+
sns.stripplot(
57+
data=df,
58+
x="Department",
59+
y="Salary",
60+
hue="Department",
61+
palette=palette,
62+
dodge=False,
63+
jitter=0.25,
64+
size=2.5,
65+
alpha=0.25,
4666
legend=False,
4767
ax=ax,
4868
)
4969

70+
# Annotate the bimodal Sales distribution to guide the viewer
71+
sales_data = df[df["Department"] == "Sales"]["Salary"]
72+
lower_peak = sales_data[sales_data < 72000].median()
73+
upper_peak = sales_data[sales_data >= 72000].median()
74+
75+
ax.annotate(
76+
"Junior cohort",
77+
xy=(1.85, lower_peak),
78+
xytext=(1.35, lower_peak - 5000),
79+
fontsize=12,
80+
fontstyle="italic",
81+
color="#555555",
82+
ha="right",
83+
va="center",
84+
arrowprops={"arrowstyle": "->", "color": "#888888", "lw": 1.0},
85+
)
86+
ax.annotate(
87+
"Senior cohort",
88+
xy=(1.85, upper_peak),
89+
xytext=(1.35, upper_peak + 5000),
90+
fontsize=12,
91+
fontstyle="italic",
92+
color="#555555",
93+
ha="right",
94+
va="center",
95+
arrowprops={"arrowstyle": "->", "color": "#888888", "lw": 1.0},
96+
)
97+
5098
# Style
51-
ax.set_xlabel("Department", fontsize=20)
52-
ax.set_ylabel("Salary ($)", fontsize=20)
53-
ax.set_title("violin-basic · seaborn · pyplots.ai", fontsize=24)
99+
ax.set_xlabel("Department", fontsize=20, labelpad=12)
100+
ax.set_ylabel("Salary ($)", fontsize=20, labelpad=12)
101+
ax.set_title("violin-basic · seaborn · pyplots.ai", fontsize=24, fontweight="medium", pad=20)
54102
ax.tick_params(axis="both", labelsize=16)
55-
ax.grid(True, alpha=0.3, linestyle="--", axis="y")
103+
104+
for spine in ax.spines.values():
105+
spine.set_visible(False)
106+
107+
ax.yaxis.grid(True, alpha=0.3, linewidth=0.6, color="#CCCCCC")
108+
ax.set_axisbelow(True)
56109

57110
# Format y-axis as currency
58111
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"${x / 1000:.0f}k"))
59112

60113
plt.tight_layout()
61-
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
114+
plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor=fig.get_facecolor())

0 commit comments

Comments
 (0)