Skip to content

Commit 17ab35b

Browse files
feat(altair): implement elbow-curve (#2338)
## Implementation: `elbow-curve` - altair Implements the **altair** version of `elbow-curve`. **File:** `plots/elbow-curve/implementations/altair.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20528203451)* --------- 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 611d5e0 commit 17ab35b

2 files changed

Lines changed: 110 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
""" pyplots.ai
2+
elbow-curve: Elbow Curve for K-Means Clustering
3+
Library: altair 6.0.0 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-26
5+
"""
6+
7+
import altair as alt
8+
import numpy as np
9+
import pandas as pd
10+
11+
12+
# Data - Simulate K-means inertia values with realistic decay
13+
np.random.seed(42)
14+
k_values = list(range(1, 12))
15+
16+
# Realistic inertia: sharp drop initially, then diminishing returns
17+
# Using exponential decay with noise
18+
base_inertia = 5000
19+
inertia = []
20+
for k in k_values:
21+
decay = base_inertia * np.exp(-0.35 * (k - 1)) + 200
22+
noise = np.random.uniform(-50, 50)
23+
inertia.append(max(decay + noise, 150))
24+
25+
# Mark optimal k (elbow point at k=4)
26+
optimal_k = 4
27+
28+
df = pd.DataFrame({"Number of Clusters (k)": k_values, "Inertia (Within-Cluster Sum of Squares)": inertia})
29+
30+
# Create base line chart
31+
line = (
32+
alt.Chart(df)
33+
.mark_line(color="#306998", strokeWidth=4)
34+
.encode(
35+
x=alt.X(
36+
"Number of Clusters (k):Q",
37+
scale=alt.Scale(domain=[0.5, 11.5]),
38+
axis=alt.Axis(tickCount=11, values=k_values),
39+
),
40+
y=alt.Y("Inertia (Within-Cluster Sum of Squares):Q", scale=alt.Scale(domain=[0, max(inertia) * 1.1])),
41+
)
42+
)
43+
44+
# Add points at each k value
45+
points = (
46+
alt.Chart(df)
47+
.mark_point(size=300, color="#306998", filled=True)
48+
.encode(
49+
x="Number of Clusters (k):Q",
50+
y="Inertia (Within-Cluster Sum of Squares):Q",
51+
tooltip=["Number of Clusters (k)", "Inertia (Within-Cluster Sum of Squares)"],
52+
)
53+
)
54+
55+
# Highlight the elbow point (optimal k)
56+
elbow_df = df[df["Number of Clusters (k)"] == optimal_k]
57+
elbow_point = (
58+
alt.Chart(elbow_df)
59+
.mark_point(size=600, color="#FFD43B", filled=True, stroke="#306998", strokeWidth=3)
60+
.encode(x="Number of Clusters (k):Q", y="Inertia (Within-Cluster Sum of Squares):Q")
61+
)
62+
63+
# Add annotation for elbow point
64+
elbow_text = (
65+
alt.Chart(elbow_df)
66+
.mark_text(align="left", baseline="bottom", dx=15, dy=-15, fontSize=20, fontWeight="bold", color="#306998")
67+
.encode(
68+
x="Number of Clusters (k):Q",
69+
y="Inertia (Within-Cluster Sum of Squares):Q",
70+
text=alt.value(f"Optimal k = {optimal_k}"),
71+
)
72+
)
73+
74+
# Combine layers
75+
chart = (
76+
(line + points + elbow_point + elbow_text)
77+
.properties(
78+
width=1600, height=900, title=alt.Title("elbow-curve · altair · pyplots.ai", fontSize=28, anchor="middle")
79+
)
80+
.configure_axis(labelFontSize=18, titleFontSize=22, gridColor="#CCCCCC", gridOpacity=0.3)
81+
.configure_view(strokeWidth=0)
82+
)
83+
84+
# Save outputs
85+
chart.save("plot.png", scale_factor=3.0)
86+
chart.save("plot.html")
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
library: altair
2+
specification_id: elbow-curve
3+
created: '2025-12-26T19:35:15Z'
4+
updated: '2025-12-26T19:37:48Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20528203451
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 6.0.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/elbow-curve/altair/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/elbow-curve/altair/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/elbow-curve/altair/plot.html
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent elbow visualization with clear annotation of optimal k=4
17+
- Well-designed layered chart combining line, points, and highlighted elbow marker
18+
- Good use of Altair declarative grammar with separate chart layers
19+
- Appropriate color scheme with Python-themed blue and contrasting yellow highlight
20+
- Interactive tooltips provide additional context on hover
21+
- Both PNG and HTML outputs generated for static and interactive viewing
22+
weaknesses:
23+
- No legend present to explain what the line/points represent
24+
- Y-axis label could note that inertia is unitless or define the metric more explicitly

0 commit comments

Comments
 (0)