Skip to content

Commit eff54be

Browse files
feat(plotly): implement histogram-cumulative (#2571)
## Implementation: `histogram-cumulative` - plotly Implements the **plotly** version of `histogram-cumulative`. **File:** `plots/histogram-cumulative/implementations/plotly.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20593348147)* --------- 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 4cb4566 commit eff54be

2 files changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
""" pyplots.ai
2+
histogram-cumulative: Cumulative Histogram
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-30
5+
"""
6+
7+
import numpy as np
8+
import plotly.graph_objects as go
9+
10+
11+
# Data: Simulated test scores with realistic distribution
12+
np.random.seed(42)
13+
scores = np.concatenate(
14+
[
15+
np.random.normal(65, 10, 300), # Average performers
16+
np.random.normal(85, 5, 150), # High performers
17+
np.random.normal(45, 8, 50), # Low performers
18+
]
19+
)
20+
scores = np.clip(scores, 0, 100) # Keep scores in valid range
21+
22+
# Calculate cumulative histogram
23+
bin_count = 25
24+
counts, bin_edges = np.histogram(scores, bins=bin_count)
25+
cumulative_counts = np.cumsum(counts)
26+
cumulative_proportion = cumulative_counts / len(scores)
27+
28+
# Use bin centers for x-axis
29+
bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
30+
31+
# Create figure
32+
fig = go.Figure()
33+
34+
# Add cumulative histogram as step line
35+
fig.add_trace(
36+
go.Scatter(
37+
x=bin_edges[1:], # Right edge of each bin
38+
y=cumulative_proportion,
39+
mode="lines",
40+
line=dict(
41+
color="#306998", # Python Blue
42+
width=4,
43+
shape="hv", # Step function (horizontal then vertical)
44+
),
45+
fill="tozeroy",
46+
fillcolor="rgba(48, 105, 152, 0.3)",
47+
name="Cumulative Distribution",
48+
hovertemplate="Score ≤ %{x:.1f}<br>Proportion: %{y:.2%}<extra></extra>",
49+
)
50+
)
51+
52+
# Add reference lines for key percentiles
53+
percentiles = [0.25, 0.50, 0.75]
54+
percentile_labels = ["25th", "50th (Median)", "75th"]
55+
for p, label in zip(percentiles, percentile_labels):
56+
x_val = np.percentile(scores, p * 100)
57+
fig.add_trace(
58+
go.Scatter(
59+
x=[x_val, x_val],
60+
y=[0, p],
61+
mode="lines",
62+
line=dict(color="#FFD43B", width=2, dash="dash"), # Python Yellow
63+
showlegend=False,
64+
hoverinfo="skip",
65+
)
66+
)
67+
fig.add_trace(
68+
go.Scatter(
69+
x=[0, x_val],
70+
y=[p, p],
71+
mode="lines",
72+
line=dict(color="#FFD43B", width=2, dash="dash"),
73+
showlegend=False,
74+
hoverinfo="skip",
75+
)
76+
)
77+
78+
# Add percentile annotations
79+
fig.add_trace(
80+
go.Scatter(
81+
x=[np.percentile(scores, 25), np.percentile(scores, 50), np.percentile(scores, 75)],
82+
y=[0.25, 0.50, 0.75],
83+
mode="markers+text",
84+
marker=dict(color="#FFD43B", size=14, line=dict(color="#306998", width=2)),
85+
text=["25%", "50%", "75%"],
86+
textposition="top right",
87+
textfont=dict(size=16, color="#306998"),
88+
showlegend=False,
89+
hovertemplate="%{text} of scores ≤ %{x:.1f}<extra></extra>",
90+
)
91+
)
92+
93+
# Update layout
94+
fig.update_layout(
95+
title=dict(text="histogram-cumulative · plotly · pyplots.ai", font=dict(size=28), x=0.5, xanchor="center"),
96+
xaxis=dict(
97+
title=dict(text="Test Score (points)", font=dict(size=22)),
98+
tickfont=dict(size=18),
99+
range=[0, 105],
100+
showgrid=True,
101+
gridcolor="rgba(0,0,0,0.1)",
102+
gridwidth=1,
103+
),
104+
yaxis=dict(
105+
title=dict(text="Cumulative Proportion", font=dict(size=22)),
106+
tickfont=dict(size=18),
107+
tickformat=".0%",
108+
range=[0, 1.05],
109+
showgrid=True,
110+
gridcolor="rgba(0,0,0,0.1)",
111+
gridwidth=1,
112+
),
113+
template="plotly_white",
114+
showlegend=True,
115+
legend=dict(x=0.02, y=0.98, font=dict(size=16), bgcolor="rgba(255,255,255,0.8)"),
116+
margin=dict(l=80, r=40, t=80, b=80),
117+
)
118+
119+
# Save outputs
120+
fig.write_image("plot.png", width=1600, height=900, scale=3)
121+
fig.write_html("plot.html", include_plotlyjs=True, full_html=True)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: plotly
2+
specification_id: histogram-cumulative
3+
created: '2025-12-30T09:31:29Z'
4+
updated: '2025-12-30T09:40:27Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20593348147
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/histogram-cumulative/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/histogram-cumulative/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/histogram-cumulative/plotly/plot.html
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent visual design with clear step function representation of cumulative
17+
distribution
18+
- Thoughtful addition of percentile reference lines (25th, 50th, 75th) with dashed
19+
yellow styling that enhances understanding
20+
- Custom hover templates provide informative tooltips showing exact proportions
21+
- Proper use of shape=hv for authentic step function appearance
22+
- Good color scheme using Python Blue and Yellow with appropriate contrast
23+
weaknesses:
24+
- Uses manual histogram calculation with np.histogram instead of Plotly native go.Histogram
25+
with cumulative_enabled=True
26+
- Legend position in upper-left could be moved to avoid potential visual overlap

0 commit comments

Comments
 (0)