Skip to content

Commit 7bc5724

Browse files
feat(pygal): implement lift-curve (#2390)
## Implementation: `lift-curve` - pygal Implements the **pygal** version of `lift-curve`. **File:** `plots/lift-curve/implementations/pygal.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20543283456)* --------- 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 3b35515 commit 7bc5724

2 files changed

Lines changed: 122 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
""" pyplots.ai
2+
lift-curve: Model Lift Chart
3+
Library: pygal 3.1.0 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-27
5+
"""
6+
7+
import numpy as np
8+
import pygal
9+
from pygal.style import Style
10+
11+
12+
# Data - Simulated customer response prediction
13+
np.random.seed(42)
14+
n_samples = 1000
15+
16+
# Generate realistic model scores and true outcomes
17+
# Good model: positive correlation between score and actual response
18+
y_score = np.random.beta(2, 5, n_samples) # Model predictions (0-1)
19+
# True labels influenced by score (better score = higher chance of response)
20+
response_prob = 0.1 + 0.6 * y_score # Base rate ~10%, top scores ~70%
21+
y_true = (np.random.random(n_samples) < response_prob).astype(int)
22+
23+
# Calculate lift curve data
24+
# Sort by score descending
25+
sorted_indices = np.argsort(y_score)[::-1]
26+
y_true_sorted = y_true[sorted_indices]
27+
28+
# Calculate cumulative metrics
29+
n_total = len(y_true)
30+
n_positive = y_true.sum()
31+
baseline_rate = n_positive / n_total
32+
33+
# Calculate lift at decile intervals (10%, 20%, ..., 100%)
34+
deciles = list(range(10, 101, 10))
35+
lift_values = []
36+
37+
for pct in deciles:
38+
n_targeted = int(n_total * pct / 100)
39+
positives_captured = y_true_sorted[:n_targeted].sum()
40+
model_rate = positives_captured / n_targeted
41+
lift = model_rate / baseline_rate if baseline_rate > 0 else 1
42+
lift_values.append(round(lift, 2))
43+
44+
# Create custom style for pyplots
45+
custom_style = Style(
46+
background="white",
47+
plot_background="white",
48+
foreground="#333333",
49+
foreground_strong="#333333",
50+
foreground_subtle="#666666",
51+
colors=("#306998", "#FFD43B"),
52+
title_font_size=56,
53+
label_font_size=36,
54+
major_label_font_size=32,
55+
legend_font_size=32,
56+
value_font_size=24,
57+
stroke_width=5,
58+
opacity=0.9,
59+
opacity_hover=1.0,
60+
)
61+
62+
# Create line chart
63+
chart = pygal.Line(
64+
width=4800,
65+
height=2700,
66+
style=custom_style,
67+
title="lift-curve · pygal · pyplots.ai",
68+
x_title="Population Targeted (%)",
69+
y_title="Lift (Model Rate / Baseline Rate)",
70+
show_dots=True,
71+
dots_size=8,
72+
stroke_style={"width": 6},
73+
fill=False,
74+
show_x_guides=False,
75+
show_y_guides=True,
76+
legend_at_bottom=True,
77+
legend_at_bottom_columns=2,
78+
truncate_legend=-1,
79+
range=(0.9, 2.2),
80+
margin=50,
81+
)
82+
83+
# X-axis labels at deciles
84+
chart.x_labels = [f"{d}%" for d in deciles]
85+
86+
# Add lift curve
87+
chart.add("Model Lift", lift_values)
88+
89+
# Add baseline reference line at y=1
90+
baseline = [1.0] * len(deciles)
91+
chart.add("Random (No Lift)", baseline)
92+
93+
# Save as PNG and HTML
94+
chart.render_to_png("plot.png")
95+
chart.render_to_file("plot.html")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library: pygal
2+
specification_id: lift-curve
3+
created: '2025-12-27T19:20:59Z'
4+
updated: '2025-12-27T19:27:46Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20543283456
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/lift-curve/pygal/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/lift-curve/pygal/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/lift-curve/pygal/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- 'Clean, professional visualization with appropriate pyplots color scheme (#306998
17+
blue, #FFD43B yellow)'
18+
- Correct lift curve implementation showing model performance vs baseline
19+
- Excellent realistic data scenario (customer response prediction) that matches
20+
spec applications
21+
- Good use of pygal style customization with custom Style configuration
22+
- Proper 4800x2700 canvas size with appropriately scaled fonts
23+
- Includes both PNG and HTML output leveraging pygal interactive capabilities
24+
weaknesses:
25+
- Legend font appears relatively small compared to axis labels
26+
- Missing value annotations at key decile points as suggested in spec
27+
- Does not fully leverage pygal interactive tooltip features

0 commit comments

Comments
 (0)