Skip to content

Commit 414bebd

Browse files
feat(plotnine): implement timeline-basic (#2473)
## Implementation: `timeline-basic` - plotnine Implements the **plotnine** version of `timeline-basic`. **File:** `plots/timeline-basic/implementations/plotnine.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20584329745)* --------- 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 70214f1 commit 414bebd

2 files changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
""" pyplots.ai
2+
timeline-basic: Event Timeline
3+
Library: plotnine 0.15.2 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-29
5+
"""
6+
7+
import pandas as pd
8+
from plotnine import (
9+
aes,
10+
element_blank,
11+
element_line,
12+
element_text,
13+
geom_point,
14+
geom_segment,
15+
geom_text,
16+
ggplot,
17+
labs,
18+
scale_color_manual,
19+
scale_y_continuous,
20+
theme,
21+
theme_minimal,
22+
)
23+
24+
25+
# Data - Software development project milestones
26+
data = {
27+
"date": pd.to_datetime(
28+
[
29+
"2024-01-15",
30+
"2024-02-20",
31+
"2024-03-10",
32+
"2024-04-05",
33+
"2024-05-15",
34+
"2024-06-20",
35+
"2024-07-10",
36+
"2024-08-25",
37+
"2024-09-15",
38+
"2024-10-30",
39+
"2024-11-20",
40+
"2024-12-15",
41+
]
42+
),
43+
"event": [
44+
"Project Kickoff",
45+
"Requirements Complete",
46+
"Architecture Review",
47+
"Backend Alpha",
48+
"Frontend Alpha",
49+
"Integration Testing",
50+
"Beta Release",
51+
"User Acceptance",
52+
"Performance Tuning",
53+
"Security Audit",
54+
"Release Candidate",
55+
"Production Launch",
56+
],
57+
"category": [
58+
"Planning",
59+
"Planning",
60+
"Planning",
61+
"Development",
62+
"Development",
63+
"Testing",
64+
"Development",
65+
"Testing",
66+
"Development",
67+
"Testing",
68+
"Release",
69+
"Release",
70+
],
71+
}
72+
73+
df = pd.DataFrame(data)
74+
75+
# Alternate label positions above and below the axis
76+
df["y_offset"] = [1 if i % 2 == 0 else -1 for i in range(len(df))]
77+
df["y_point"] = df["y_offset"] * 0.35
78+
df["y_label"] = df["y_offset"] * 0.65
79+
80+
# Split dataframe for alternating text positions
81+
df_above = df[df["y_offset"] == 1].copy()
82+
df_below = df[df["y_offset"] == -1].copy()
83+
84+
# Category colors - using colorblind-safe palette
85+
category_colors = {
86+
"Planning": "#306998", # Python Blue
87+
"Development": "#FFD43B", # Python Yellow
88+
"Testing": "#E69F00", # Orange
89+
"Release": "#009E73", # Green
90+
}
91+
92+
# Create timeline plot
93+
plot = (
94+
ggplot(df, aes(x="date", y=0))
95+
# Vertical connector lines from axis to points
96+
+ geom_segment(aes(x="date", xend="date", y=0, yend="y_point"), color="#888888", size=0.8)
97+
# Timeline axis line
98+
+ geom_segment(
99+
aes(x=df["date"].min() - pd.Timedelta(days=15), xend=df["date"].max() + pd.Timedelta(days=15), y=0, yend=0),
100+
color="#333333",
101+
size=1.5,
102+
)
103+
# Event points on the timeline
104+
+ geom_point(aes(x="date", y="y_point", color="category"), size=8)
105+
# Event labels above the axis
106+
+ geom_text(data=df_above, mapping=aes(x="date", y="y_label", label="event"), size=11, color="#333333", va="bottom")
107+
# Event labels below the axis
108+
+ geom_text(data=df_below, mapping=aes(x="date", y="y_label", label="event"), size=11, color="#333333", va="top")
109+
# Styling
110+
+ scale_color_manual(values=category_colors)
111+
+ scale_y_continuous(limits=(-1.2, 1.2))
112+
+ labs(title="timeline-basic · plotnine · pyplots.ai", x="Date", y="", color="Phase")
113+
+ theme_minimal()
114+
+ theme(
115+
figure_size=(16, 9),
116+
plot_title=element_text(size=24, ha="center"),
117+
axis_title_x=element_text(size=20),
118+
axis_text_x=element_text(size=16),
119+
axis_text_y=element_blank(),
120+
axis_ticks_major_y=element_blank(),
121+
panel_grid_major_y=element_blank(),
122+
panel_grid_minor_y=element_blank(),
123+
panel_grid_major_x=element_line(color="#cccccc", alpha=0.3),
124+
panel_grid_minor_x=element_blank(),
125+
legend_title=element_text(size=18),
126+
legend_text=element_text(size=16),
127+
legend_position="bottom",
128+
)
129+
)
130+
131+
# Save
132+
plot.save("plot.png", dpi=300, verbose=False)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
library: plotnine
2+
specification_id: timeline-basic
3+
created: '2025-12-29T22:49:17Z'
4+
updated: '2025-12-29T22:57:58Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20584329745
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 0.15.2
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/timeline-basic/plotnine/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/timeline-basic/plotnine/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent alternating label placement above/below axis prevents text overlap entirely
17+
- Colorblind-safe palette with four distinct, accessible colors for phases
18+
- Clean implementation of timeline using ggplot grammar of graphics
19+
- Well-structured code following KISS principles
20+
- Realistic software development project scenario with meaningful milestones
21+
weaknesses:
22+
- Event spacing is very uniform (roughly monthly) - more varied spacing would better
23+
demonstrate timeline capabilities
24+
- Axis label Date could be more descriptive (e.g., Project Timeline 2024)

0 commit comments

Comments
 (0)