Skip to content

Commit 706687f

Browse files
feat(matplotlib): implement elbow-curve (#2345)
## Implementation: `elbow-curve` - matplotlib Implements the **matplotlib** version of `elbow-curve`. **File:** `plots/elbow-curve/implementations/matplotlib.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20528202012)* --------- 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 ce273a0 commit 706687f

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
""" pyplots.ai
2+
elbow-curve: Elbow Curve for K-Means Clustering
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-26
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
10+
11+
# Simulate realistic inertia values for K-means elbow curve
12+
# Based on typical clustering behavior: sharp decline followed by gradual decrease
13+
np.random.seed(42)
14+
k_values = np.arange(1, 11)
15+
16+
# Generate realistic inertia decay pattern
17+
# Inertia typically follows exponential decay with the "elbow" around k=4
18+
base_inertia = 5000
19+
inertias = []
20+
for k in k_values:
21+
# Exponential decay with elbow effect at k=4
22+
if k <= 4:
23+
inertia = base_inertia * np.exp(-0.35 * (k - 1))
24+
else:
25+
inertia = base_inertia * np.exp(-0.35 * 3) * np.exp(-0.15 * (k - 4))
26+
# Add small random noise for realism
27+
inertia += np.random.uniform(-50, 50)
28+
inertias.append(max(inertia, 100))
29+
30+
inertias = np.array(inertias)
31+
32+
# Identify the elbow point (k=4 is the optimal cluster count)
33+
elbow_k = 4
34+
elbow_inertia = inertias[elbow_k - 1]
35+
36+
# Create plot (4800x2700 px at 300 dpi = 16x9 inches)
37+
fig, ax = plt.subplots(figsize=(16, 9))
38+
39+
# Plot the elbow curve
40+
ax.plot(
41+
k_values,
42+
inertias,
43+
color="#306998",
44+
linewidth=3,
45+
marker="o",
46+
markersize=12,
47+
markerfacecolor="#FFD43B",
48+
markeredgecolor="#306998",
49+
markeredgewidth=2,
50+
label="Inertia",
51+
)
52+
53+
# Highlight the elbow point
54+
ax.scatter([elbow_k], [elbow_inertia], s=400, color="#FFD43B", edgecolors="#306998", linewidths=3, zorder=5)
55+
ax.annotate(
56+
f"Elbow Point\n(k={elbow_k})",
57+
xy=(elbow_k, elbow_inertia),
58+
xytext=(elbow_k + 1.8, elbow_inertia + 600),
59+
fontsize=18,
60+
fontweight="bold",
61+
color="#306998",
62+
arrowprops={"arrowstyle": "->", "color": "#306998", "lw": 2.5},
63+
)
64+
65+
# Labels and styling
66+
ax.set_xlabel("Number of Clusters (k)", fontsize=20)
67+
ax.set_ylabel("Inertia (Within-Cluster Sum of Squares)", fontsize=20)
68+
ax.set_title("elbow-curve · matplotlib · pyplots.ai", fontsize=24)
69+
ax.tick_params(axis="both", labelsize=16)
70+
ax.set_xticks(k_values)
71+
ax.grid(True, alpha=0.3, linestyle="--")
72+
73+
# Add subtle shading to show diminishing returns region
74+
ax.axvspan(elbow_k, max(k_values), alpha=0.1, color="#306998", label="Diminishing Returns")
75+
76+
plt.tight_layout()
77+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: matplotlib
2+
specification_id: elbow-curve
3+
created: '2025-12-26T19:36:06Z'
4+
updated: '2025-12-26T19:41:50Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20528202012
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/elbow-curve/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/elbow-curve/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent elbow curve visualization with clear elbow point identification at k=4
17+
- Professional annotation with arrow pointing to the optimal cluster count
18+
- Thoughtful diminishing returns shaded region adds educational value
19+
- 'Color scheme (Python blue #306998 and yellow #FFD43B) is visually appealing and
20+
brand-consistent'
21+
- Realistic inertia decay pattern that demonstrates the typical K-means behavior
22+
- Clean, readable code following KISS principles
23+
weaknesses:
24+
- Legend is defined but not displayed (ax.legend() call is missing), though the
25+
label parameter and axvspan label are set
26+
- Y-axis label could include units or clarify unitless nature of inertia

0 commit comments

Comments
 (0)