Skip to content

Commit dbe947b

Browse files
feat(pygal): implement line-timeseries-rolling (#2816)
## Implementation: `line-timeseries-rolling` - pygal Implements the **pygal** version of `line-timeseries-rolling`. **File:** `plots/line-timeseries-rolling/implementations/pygal.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20602452872)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent f89167e commit dbe947b

2 files changed

Lines changed: 129 additions & 0 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
""" pyplots.ai
2+
line-timeseries-rolling: Time Series with Rolling Average Overlay
3+
Library: pygal 3.1.0 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-30
5+
"""
6+
7+
import random
8+
from datetime import datetime, timedelta
9+
10+
import pygal
11+
from pygal.style import Style
12+
13+
14+
# Seed for reproducibility
15+
random.seed(42)
16+
17+
# Generate daily temperature readings for 4 months
18+
start_date = datetime(2024, 1, 1)
19+
dates = [start_date + timedelta(days=i) for i in range(120)]
20+
21+
# Generate temperature data with seasonal trend and noise
22+
temperatures = []
23+
for i in range(120):
24+
# Seasonal variation: winter to early spring
25+
seasonal = 5 + 8 * (i / 120) # Gradual warming from 5°C to 13°C
26+
noise = random.gauss(0, 3)
27+
temp = seasonal + noise
28+
temperatures.append(round(temp, 1))
29+
30+
# Calculate 7-day rolling average (None for first 6 days)
31+
window_size = 7
32+
rolling_avg = []
33+
for i in range(len(temperatures)):
34+
if i < window_size - 1:
35+
rolling_avg.append(None) # pygal handles None as gaps
36+
else:
37+
window = temperatures[i - window_size + 1 : i + 1]
38+
avg = sum(window) / window_size
39+
rolling_avg.append(round(avg, 1))
40+
41+
# Custom style for 4800x2700 canvas with larger fonts
42+
custom_style = Style(
43+
background="white",
44+
plot_background="white",
45+
foreground="#333333",
46+
foreground_strong="#333333",
47+
foreground_subtle="#666666",
48+
colors=("#306998", "#E67E22"), # Python Blue for raw, Orange for rolling avg (better visibility)
49+
title_font_size=72,
50+
label_font_size=48,
51+
major_label_font_size=42,
52+
legend_font_size=42,
53+
value_font_size=36,
54+
guide_stroke_color="#cccccc",
55+
guide_stroke_dasharray="2,4",
56+
)
57+
58+
# Create line chart
59+
chart = pygal.Line(
60+
width=4800,
61+
height=2700,
62+
style=custom_style,
63+
title="line-timeseries-rolling · pygal · pyplots.ai",
64+
x_title="Date",
65+
y_title="Temperature (°C)",
66+
show_x_guides=False,
67+
show_y_guides=True,
68+
x_label_rotation=45,
69+
show_legend=True,
70+
legend_at_bottom=True,
71+
legend_at_bottom_columns=2, # Keep legend items together in 2 columns
72+
legend_box_size=24, # Larger legend box for visibility
73+
truncate_legend=-1,
74+
show_dots=False,
75+
stroke_style={"width": 4},
76+
margin=60,
77+
)
78+
79+
# Add raw temperature data (lighter line)
80+
chart.add("Raw Temperature", temperatures, stroke_style={"width": 2})
81+
82+
# Add rolling average (prominent line)
83+
chart.add("7-Day Rolling Average", rolling_avg, stroke_style={"width": 6})
84+
85+
# Set x-axis labels - show every 2 weeks
86+
x_labels = []
87+
x_labels_major = []
88+
for d in dates:
89+
if d.day in [1, 15]: # 1st and 15th of each month
90+
label = d.strftime("%b %d")
91+
x_labels.append(label)
92+
x_labels_major.append(label)
93+
else:
94+
x_labels.append("")
95+
96+
chart.x_labels = x_labels
97+
chart.x_labels_major = x_labels_major
98+
99+
# Save as HTML and PNG
100+
chart.render_to_file("plot.html")
101+
chart.render_to_png("plot.png")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
library: pygal
2+
specification_id: line-timeseries-rolling
3+
created: '2025-12-30T17:49:00Z'
4+
updated: '2025-12-30T18:07:10Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20602452872
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 3.1.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-timeseries-rolling/pygal/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-timeseries-rolling/pygal/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/line-timeseries-rolling/pygal/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent visual distinction between raw data (thin blue line) and rolling average
17+
(thick orange line) following spec guidance
18+
- Proper handling of rolling average with None values for first 6 days (pygal renders
19+
this as gaps correctly)
20+
- Good colorblind-safe color choices with Python Blue and contrasting Orange
21+
- Legend clearly indicates the 7-day window size as recommended by spec
22+
- Well-scaled font sizes for the 4800x2700 canvas with custom Style
23+
- Clean bi-weekly x-axis labeling prevents crowding
24+
weaknesses:
25+
- Grid visibility could be improved - x-axis guides are disabled (show_x_guides=False)
26+
while spec suggests grid lines on both axes improve readability
27+
- Font sizes in custom_style are larger than pygal.md guidelines suggest, though
28+
this works well for the output

0 commit comments

Comments
 (0)