Skip to content

Commit c8dd46e

Browse files
feat(letsplot): implement errorbar-asymmetric (#2814)
## Implementation: `errorbar-asymmetric` - letsplot Implements the **letsplot** version of `errorbar-asymmetric`. **File:** `plots/errorbar-asymmetric/implementations/letsplot.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20602452663)* --------- 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 cd224e1 commit c8dd46e

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
""" pyplots.ai
2+
errorbar-asymmetric: Asymmetric Error Bars Plot
3+
Library: letsplot 4.8.2 | Python 3.13.11
4+
Quality: 93/100 | Created: 2025-12-30
5+
"""
6+
# ruff: noqa: F405
7+
8+
import numpy as np
9+
import pandas as pd
10+
from lets_plot import * # noqa: F403
11+
12+
13+
LetsPlot.setup_html()
14+
15+
# Data - Quarterly sales performance with asymmetric confidence intervals
16+
np.random.seed(42)
17+
quarters = ["Q1", "Q2", "Q3", "Q4"]
18+
sales = [85, 92, 78, 105] # Sales in thousands
19+
# Asymmetric errors: different upside/downside uncertainty
20+
error_lower = [8, 5, 12, 7] # Lower error (downside risk)
21+
error_upper = [15, 18, 6, 22] # Upper error (upside potential)
22+
23+
df = pd.DataFrame(
24+
{
25+
"quarter": quarters,
26+
"sales": sales,
27+
"ymin": [s - el for s, el in zip(sales, error_lower, strict=True)],
28+
"ymax": [s + eu for s, eu in zip(sales, error_upper, strict=True)],
29+
}
30+
)
31+
32+
# Plot
33+
plot = (
34+
ggplot(df, aes(x="quarter", y="sales"))
35+
+ geom_point(size=6, color="#306998", alpha=0.9)
36+
+ geom_errorbar(aes(ymin="ymin", ymax="ymax"), width=0.3, size=1.5, color="#306998")
37+
+ labs(
38+
x="Quarter",
39+
y="Sales (thousands USD)",
40+
title="errorbar-asymmetric · letsplot · pyplots.ai",
41+
caption="Error bars represent 10th-90th percentile forecast range",
42+
)
43+
+ scale_y_continuous(limits=[50, 140])
44+
+ theme_minimal()
45+
+ theme(
46+
plot_title=element_text(size=24, face="bold"),
47+
axis_title=element_text(size=20),
48+
axis_text=element_text(size=16),
49+
plot_caption=element_text(size=14),
50+
panel_grid_major=element_line(color="#cccccc", size=0.3),
51+
panel_grid_minor=element_blank(),
52+
)
53+
+ ggsize(1600, 900)
54+
)
55+
56+
# Save
57+
ggsave(plot, "plot.png", scale=3, path=".")
58+
59+
# Save HTML for interactive version
60+
ggsave(plot, "plot.html", path=".")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: letsplot
2+
specification_id: errorbar-asymmetric
3+
created: '2025-12-30T17:48:53Z'
4+
updated: '2025-12-30T17:57:28Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20602452663
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 4.8.2
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/errorbar-asymmetric/letsplot/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/errorbar-asymmetric/letsplot/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/errorbar-asymmetric/letsplot/plot.html
13+
quality_score: 93
14+
review:
15+
strengths:
16+
- Excellent visual clarity with well-sized elements and readable text at all levels
17+
- Clear demonstration of asymmetric error bars with visible caps
18+
- Proper title format and informative caption explaining the error bounds
19+
- Clean, KISS-compliant code structure following lets-plot conventions
20+
- Good use of theme_minimal() with subtle grid customization
21+
- Generates both PNG and HTML outputs as expected for lets-plot
22+
weaknesses:
23+
- The interactive HTML version does not include tooltips to show exact values on
24+
hover
25+
- Grid/Legend score reduced because there is no formal legend element (caption serves
26+
the purpose but is not a legend)

0 commit comments

Comments
 (0)