Skip to content

Commit 31cee04

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

2 files changed

Lines changed: 239 additions & 146 deletions

File tree

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,74 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
ecdf-basic: Basic ECDF Plot
3-
Library: letsplot 4.8.2 | Python 3.13.11
4-
Quality: 96/100 | Created: 2025-12-23
3+
Library: letsplot 4.9.0 | Python 3.14.4
4+
Quality: 87/100 | Updated: 2026-04-24
55
"""
66

7+
import os
8+
79
import numpy as np
810
import pandas as pd
9-
from lets_plot import * # noqa: F403
10-
from lets_plot.export import ggsave as export_ggsave
11+
from lets_plot import (
12+
LetsPlot,
13+
aes,
14+
element_blank,
15+
element_line,
16+
element_rect,
17+
element_text,
18+
ggplot,
19+
ggsize,
20+
labs,
21+
scale_y_continuous,
22+
stat_ecdf,
23+
theme,
24+
theme_minimal,
25+
)
26+
from lets_plot.export import ggsave
27+
1128

29+
LetsPlot.setup_html()
1230

13-
LetsPlot.setup_html() # noqa: F405
31+
# Theme tokens
32+
THEME = os.getenv("ANYPLOT_THEME", "light")
33+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
34+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
35+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
36+
GRID = "#C9C7C1" if THEME == "light" else "#565551"
37+
BRAND = "#009E73"
1438

15-
# Data - Response times (ms) from a web service
39+
# Data — Web service response times (ms) with mixed distribution
1640
np.random.seed(42)
1741
response_times = np.concatenate(
18-
[
19-
np.random.exponential(scale=50, size=150), # Fast responses
20-
np.random.normal(loc=200, scale=30, size=50), # Slower responses
21-
]
42+
[np.random.exponential(scale=50, size=150), np.random.normal(loc=200, scale=30, size=50)]
2243
)
44+
df = pd.DataFrame({"response_time": response_times})
2345

24-
# Sort data and calculate ECDF values
25-
sorted_values = np.sort(response_times)
26-
ecdf_values = np.arange(1, len(sorted_values) + 1) / len(sorted_values)
27-
28-
df = pd.DataFrame({"response_time": sorted_values, "ecdf": ecdf_values})
29-
30-
# Plot - ECDF as step function
46+
# Plot — ECDF using stat_ecdf with step geometry
3147
plot = (
32-
ggplot(df, aes(x="response_time", y="ecdf")) # noqa: F405
33-
+ geom_step(color="#306998", size=2) # noqa: F405
34-
+ labs( # noqa: F405
35-
x="Response Time (ms)", y="Cumulative Proportion", title="ecdf-basic · letsplot · pyplots.ai"
48+
ggplot(df, aes(x="response_time"))
49+
+ stat_ecdf(geom="step", color=BRAND, size=2)
50+
+ labs(
51+
x="Response Time (ms)",
52+
y="Cumulative Proportion",
53+
title="Web Service Response Times · ecdf-basic · letsplot · anyplot.ai",
3654
)
37-
+ scale_y_continuous(limits=[0, 1], breaks=[0, 0.25, 0.5, 0.75, 1.0]) # noqa: F405
38-
+ ggsize(1600, 900) # noqa: F405
39-
+ theme_minimal() # noqa: F405
40-
+ theme( # noqa: F405
41-
axis_text=element_text(size=16), # noqa: F405
42-
axis_title=element_text(size=20), # noqa: F405
43-
plot_title=element_text(size=24), # noqa: F405
44-
panel_grid_major=element_line(color="#CCCCCC", size=0.5, linetype="dashed"), # noqa: F405
45-
panel_grid_minor=element_blank(), # noqa: F405
55+
+ scale_y_continuous(limits=[0, 1], breaks=[0, 0.25, 0.5, 0.75, 1.0])
56+
+ ggsize(1600, 900)
57+
+ theme_minimal()
58+
+ theme(
59+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
60+
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
61+
legend_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
62+
panel_grid_major=element_line(color=GRID, size=0.6),
63+
panel_grid_minor=element_blank(),
64+
axis_line=element_line(color=INK_SOFT, size=0.6),
65+
axis_ticks=element_line(color=INK_SOFT, size=0.5),
66+
axis_text=element_text(size=16, color=INK_SOFT),
67+
axis_title=element_text(size=20, color=INK),
68+
plot_title=element_text(size=24, color=INK),
4669
)
4770
)
4871

49-
# Save PNG (scale 3x to get 4800 x 2700 px)
50-
export_ggsave(plot, filename="plot.png", path=".", scale=3)
51-
52-
# Save HTML for interactive version
53-
export_ggsave(plot, filename="plot.html", path=".")
72+
# Save
73+
ggsave(plot, filename=f"plot-{THEME}.png", path=".", scale=3)
74+
ggsave(plot, filename=f"plot-{THEME}.html", path=".")

0 commit comments

Comments
 (0)