Skip to content

Commit 3ad6948

Browse files
update(bump-basic): altair — comprehensive quality review
Restructured data and color encoding for cleaner Altair idiom.
1 parent 1e072e3 commit 3ad6948

4 files changed

Lines changed: 91 additions & 91 deletions

File tree

Lines changed: 82 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,101 @@
1-
""" pyplots.ai
1+
"""pyplots.ai
22
bump-basic: Basic Bump Chart
3-
Library: altair 6.0.0 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: altair 6.0.0 | Python 3.14.3
4+
Quality: /100 | Updated: 2026-02-22
55
"""
66

77
import altair as alt
88
import pandas as pd
99

1010

11-
# Data - Sports league standings over 6 matchweeks
12-
data = {
13-
"Team": (
14-
["Arsenal"] * 6
15-
+ ["Chelsea"] * 6
16-
+ ["Liverpool"] * 6
17-
+ ["Man City"] * 6
18-
+ ["Man United"] * 6
19-
+ ["Tottenham"] * 6
20-
),
21-
"Week": ["Week 1", "Week 2", "Week 3", "Week 4", "Week 5", "Week 6"] * 6,
22-
"Rank": [
23-
# Arsenal: Starts 3rd, rises to 1st, stays competitive
24-
3,
25-
2,
26-
1,
27-
1,
28-
2,
29-
1,
30-
# Chelsea: Mid-table consistency
31-
4,
32-
4,
33-
3,
34-
4,
35-
3,
36-
3,
37-
# Liverpool: Starts 1st, drops mid-season, recovers
38-
1,
39-
1,
40-
2,
41-
3,
42-
1,
43-
2,
44-
# Man City: Slow start, climbs steadily
45-
5,
46-
5,
47-
4,
48-
2,
49-
4,
50-
4,
51-
# Man United: Volatile rankings
52-
2,
53-
3,
54-
5,
55-
5,
56-
5,
57-
5,
58-
# Tottenham: Bottom position throughout
59-
6,
60-
6,
61-
6,
62-
6,
63-
6,
64-
6,
65-
],
66-
}
11+
# Data - Sports league standings over 6 matchweeks (no random data)
12+
teams = ["Arsenal", "Chelsea", "Liverpool", "Man City", "Man United", "Tottenham"]
13+
weeks = ["Week 1", "Week 2", "Week 3", "Week 4", "Week 5", "Week 6"]
14+
ranks = [
15+
# Arsenal: Starts 3rd, rises to 1st, stays competitive
16+
3,
17+
2,
18+
1,
19+
1,
20+
2,
21+
1,
22+
# Chelsea: Mid-table consistency
23+
4,
24+
4,
25+
3,
26+
4,
27+
3,
28+
3,
29+
# Liverpool: Starts 1st, drops mid-season, recovers
30+
1,
31+
1,
32+
2,
33+
3,
34+
1,
35+
2,
36+
# Man City: Slow start, climbs steadily
37+
5,
38+
5,
39+
4,
40+
2,
41+
4,
42+
4,
43+
# Man United: Volatile rankings
44+
2,
45+
3,
46+
5,
47+
5,
48+
5,
49+
5,
50+
# Tottenham: Bottom position throughout
51+
6,
52+
6,
53+
6,
54+
6,
55+
6,
56+
6,
57+
]
6758

68-
df = pd.DataFrame(data)
59+
df = pd.DataFrame({"Team": [t for t in teams for _ in weeks], "Week": weeks * len(teams), "Rank": ranks})
6960

70-
# Define color palette (Python Blue first, then colorblind-safe colors)
71-
colors = ["#306998", "#FFD43B", "#E15759", "#59A14F", "#9C755F", "#BAB0AC"]
61+
# Colorblind-safe palette (Python Blue first)
62+
colors = ["#306998", "#FFD43B", "#E15759", "#59A14F", "#B07AA1", "#76B7B2"]
7263

73-
# Create bump chart - lines connecting rankings
64+
# Interactive highlight — distinctive Altair feature
65+
highlight = alt.selection_point(fields=["Team"], on="pointerover")
66+
67+
# Shared encodings
68+
x = alt.X("Week:O", title="Match Week", axis=alt.Axis(labelFontSize=18, titleFontSize=22))
69+
y = alt.Y(
70+
"Rank:Q",
71+
title="League Position",
72+
scale=alt.Scale(domain=[1, 6], reverse=True),
73+
axis=alt.Axis(labelFontSize=18, titleFontSize=22, tickMinStep=1, values=[1, 2, 3, 4, 5, 6]),
74+
)
75+
color = alt.Color(
76+
"Team:N",
77+
title="Team",
78+
scale=alt.Scale(domain=teams, range=colors),
79+
legend=alt.Legend(labelFontSize=16, titleFontSize=18, symbolSize=200),
80+
)
81+
82+
# Lines — dim non-highlighted teams on hover
7483
lines = (
7584
alt.Chart(df)
76-
.mark_line(strokeWidth=4, opacity=0.8)
77-
.encode(
78-
x=alt.X("Week:O", title="Match Week", axis=alt.Axis(labelFontSize=18, titleFontSize=22)),
79-
y=alt.Y(
80-
"Rank:Q",
81-
title="League Position",
82-
scale=alt.Scale(domain=[1, 6], reverse=True),
83-
axis=alt.Axis(labelFontSize=18, titleFontSize=22, tickMinStep=1, values=[1, 2, 3, 4, 5, 6]),
84-
),
85-
color=alt.Color(
86-
"Team:N",
87-
title="Team",
88-
scale=alt.Scale(domain=df["Team"].unique().tolist(), range=colors),
89-
legend=alt.Legend(labelFontSize=16, titleFontSize=18),
90-
),
91-
)
85+
.mark_line(strokeWidth=4)
86+
.encode(x=x, y=y, color=color, opacity=alt.condition(highlight, alt.value(1), alt.value(0.3)))
87+
.add_params(highlight)
9288
)
9389

94-
# Add points at each period for clarity
90+
# Points at each period for clarity
9591
points = (
9692
alt.Chart(df)
97-
.mark_point(size=250, filled=True, opacity=1)
93+
.mark_point(size=250, filled=True)
9894
.encode(
9995
x=alt.X("Week:O"),
10096
y=alt.Y("Rank:Q", scale=alt.Scale(domain=[1, 6], reverse=True)),
101-
color=alt.Color("Team:N", scale=alt.Scale(domain=df["Team"].unique().tolist(), range=colors)),
97+
color=alt.Color("Team:N", scale=alt.Scale(domain=teams, range=colors)),
98+
opacity=alt.condition(highlight, alt.value(1), alt.value(0.3)),
10299
tooltip=["Team:N", "Week:O", "Rank:Q"],
103100
)
104101
)
@@ -107,12 +104,12 @@
107104
chart = (
108105
(lines + points)
109106
.properties(width=1600, height=900, title=alt.Title("bump-basic · altair · pyplots.ai", fontSize=28))
110-
.configure_axis(grid=True, gridOpacity=0.3, gridDash=[4, 4])
107+
.configure_axis(grid=True, gridOpacity=0.2, gridDash=[4, 4])
111108
.configure_view(strokeWidth=0)
112109
)
113110

114111
# Save as PNG (1600 × 900 × 3 = 4800 × 2700)
115112
chart.save("plot.png", scale_factor=3.0)
116113

117-
# Save interactive HTML version
118-
chart.interactive().save("plot.html")
114+
# Save interactive HTML version (hover highlights team)
115+
chart.save("plot.html")

plots/bump-basic/metadata/altair.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
library: altair
22
specification_id: bump-basic
33
created: '2025-12-23T09:18:27Z'
4-
updated: '2025-12-23T09:23:38Z'
5-
generated_by: claude-opus-4-5-20251101
4+
updated: '2026-02-22T20:55:00+00:00'
5+
generated_by: claude-opus-4-6
66
workflow_run: 20456609780
77
issue: 0
8-
python_version: 3.13.11
9-
library_version: 6.0.0
8+
python_version: '3.14.3'
9+
library_version: '6.0.0'
1010
preview_url: https://storage.googleapis.com/pyplots-images/plots/bump-basic/altair/plot.png
1111
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bump-basic/altair/plot_thumb.png
1212
preview_html: https://storage.googleapis.com/pyplots-images/plots/bump-basic/altair/plot.html
13-
quality_score: 92
13+
quality_score: null
1414
impl_tags:
1515
dependencies: []
1616
techniques:

plots/bump-basic/specification.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ A bump chart visualizes how rankings change over time by plotting rank positions
1717
- `period` (categorical or time) - Time points for ranking snapshots
1818
- `rank` (integer) - Position at each period (1 = highest rank)
1919
- Size: 5-10 entities, 4-8 periods typical
20+
- Example: Formula 1 driver standings over a 10-race season
2021

2122
## Notes
2223

plots/bump-basic/specification.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ title: Basic Bump Chart
66

77
# Specification tracking
88
created: 2025-12-15T20:42:43Z
9-
updated: 2025-12-15T20:42:43Z
9+
updated: 2026-02-22T12:00:00Z
1010
issue: 982
1111
suggested: MarkusNeusinger
1212

@@ -18,9 +18,11 @@ tags:
1818
data_type:
1919
- categorical
2020
- ordinal
21+
- timeseries
2122
domain:
2223
- general
2324
features:
2425
- basic
2526
- ranking
2627
- temporal
28+
- comparison

0 commit comments

Comments
 (0)