Skip to content

Commit 1cb57ef

Browse files
feat(altair): implement ecdf-basic (#5357)
## Implementation: `ecdf-basic` - python/altair Implements the **python/altair** version of `ecdf-basic`. **File:** `plots/ecdf-basic/implementations/python/altair.py` **Parent Issue:** #976 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24890589158)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 2d94cdf commit 1cb57ef

2 files changed

Lines changed: 209 additions & 143 deletions

File tree

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,72 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
ecdf-basic: Basic ECDF Plot
3-
Library: altair 6.0.0 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: altair 6.1.0 | Python 3.14.4
4+
Quality: 86/100 | Updated: 2026-04-24
55
"""
66

7+
import os
8+
79
import altair as alt
810
import numpy as np
911
import pandas as pd
1012

1113

12-
# Data
14+
# Theme tokens
15+
THEME = os.getenv("ANYPLOT_THEME", "light")
16+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
17+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
18+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
19+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
20+
BRAND = "#009E73"
21+
22+
# Data: API response latency from a production web service
1323
np.random.seed(42)
14-
values = np.random.normal(loc=50, scale=15, size=200)
24+
response_times_ms = np.random.normal(loc=120, scale=35, size=250)
25+
response_times_ms = np.clip(response_times_ms, 20, None)
1526

16-
# Sort values and compute ECDF
17-
sorted_values = np.sort(values)
18-
ecdf_y = np.arange(1, len(sorted_values) + 1) / len(sorted_values)
27+
sorted_latency = np.sort(response_times_ms)
28+
cumulative_proportion = np.arange(1, len(sorted_latency) + 1) / len(sorted_latency)
1929

20-
df = pd.DataFrame({"value": sorted_values, "ecdf": ecdf_y})
30+
df = pd.DataFrame({"latency_ms": sorted_latency, "cumulative": cumulative_proportion})
2131

2232
# Chart
2333
chart = (
2434
alt.Chart(df)
25-
.mark_line(interpolate="step-after", strokeWidth=3, color="#306998")
35+
.mark_line(interpolate="step-after", strokeWidth=3.5, color=BRAND)
2636
.encode(
27-
x=alt.X("value:Q", title="Value", scale=alt.Scale(nice=True)),
28-
y=alt.Y("ecdf:Q", title="Cumulative Proportion", scale=alt.Scale(domain=[0, 1])),
29-
tooltip=["value:Q", "ecdf:Q"],
37+
x=alt.X("latency_ms:Q", title="API Response Time (ms)", scale=alt.Scale(nice=True)),
38+
y=alt.Y(
39+
"cumulative:Q",
40+
title="Cumulative Proportion",
41+
scale=alt.Scale(domain=[0, 1]),
42+
axis=alt.Axis(format=".0%", tickCount=11),
43+
),
44+
tooltip=[
45+
alt.Tooltip("latency_ms:Q", title="Latency (ms)", format=".1f"),
46+
alt.Tooltip("cumulative:Q", title="Proportion", format=".3f"),
47+
],
48+
)
49+
.properties(
50+
width=1600,
51+
height=900,
52+
background=PAGE_BG,
53+
title=alt.Title("ecdf-basic · altair · anyplot.ai", fontSize=28, color=INK),
54+
)
55+
.interactive()
56+
.configure_view(fill=PAGE_BG, strokeWidth=0)
57+
.configure_axis(
58+
domainColor=INK_SOFT,
59+
tickColor=INK_SOFT,
60+
gridColor=INK,
61+
gridOpacity=0.10,
62+
labelColor=INK_SOFT,
63+
titleColor=INK,
64+
labelFontSize=18,
65+
titleFontSize=22,
3066
)
31-
.properties(width=1600, height=900, title=alt.Title("ecdf-basic · altair · pyplots.ai", fontSize=28))
32-
.configure_axis(labelFontSize=18, titleFontSize=22, gridOpacity=0.3, gridDash=[4, 4])
33-
.configure_view(strokeWidth=0)
67+
.configure_title(color=INK)
3468
)
3569

3670
# Save
37-
chart.save("plot.png", scale_factor=3.0)
38-
chart.save("plot.html")
71+
chart.save(f"plot-{THEME}.png", scale_factor=3.0)
72+
chart.save(f"plot-{THEME}.html")

0 commit comments

Comments
 (0)