Skip to content

Commit 470cc08

Browse files
update(bullet-basic): plotnine — comprehensive quality review
Comprehensive quality review improving ggplot2 idioms and band labels.
1 parent 1e072e3 commit 470cc08

2 files changed

Lines changed: 43 additions & 19 deletions

File tree

plots/bullet-basic/implementations/plotnine.py

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
""" pyplots.ai
1+
"""pyplots.ai
22
bullet-basic: Basic Bullet Chart
3-
Library: plotnine 0.15.2 | Python 3.13.11
4-
Quality: 94/100 | Created: 2025-12-23
3+
Library: plotnine 0.15.3 | Python 3.14.3
4+
Quality: /100 | Updated: 2026-02-22
55
"""
66

77
import pandas as pd
88
from plotnine import (
99
aes,
1010
element_blank,
11+
element_line,
1112
element_text,
1213
geom_rect,
1314
geom_segment,
@@ -51,9 +52,11 @@
5152
)
5253
range_data.append({"y": y_pos, "xmin": (m["ranges"][1] / max_val) * 100, "xmax": 100, "band": "Good"})
5354

54-
# Actual value bar
55+
# Actual value bar - format label as integer when possible
5556
actual_pct = (m["actual"] / max_val) * 100
56-
actual_data.append({"y": y_pos, "xmin": 0, "xmax": actual_pct, "label": m["label"], "actual": m["actual"]})
57+
val = m["actual"]
58+
val_str = str(int(val)) if val == int(val) else str(val)
59+
actual_data.append({"y": y_pos, "xmin": 0, "xmax": actual_pct, "label": m["label"], "actual": val_str})
5760

5861
# Target marker
5962
target_pct = (m["target"] / max_val) * 100
@@ -63,12 +66,26 @@
6366
df_actual = pd.DataFrame(actual_data)
6467
df_target = pd.DataFrame(target_data)
6568

66-
# Grayscale colors for qualitative bands (good=light, satisfactory=medium, poor=dark)
69+
# Grayscale colors for qualitative bands (poor=dark, satisfactory=medium, good=light)
6770
band_colors = {"Poor": "#707070", "Satisfactory": "#A0A0A0", "Good": "#D0D0D0"}
6871

6972
# Bar height parameters
70-
range_height = 0.65
71-
actual_height = 0.28
73+
range_height = 0.6
74+
actual_height = 0.25
75+
76+
# Band legend labels centered in each zone of the bottom metric (Satisfaction: 50%, 70%, 100%)
77+
sat = metrics[-1]
78+
sat_max = sat["ranges"][-1]
79+
poor_mid = (sat["ranges"][0] / sat_max) * 50
80+
satis_mid = ((sat["ranges"][0] + sat["ranges"][1]) / (2 * sat_max)) * 100
81+
good_mid = ((sat["ranges"][1] + sat_max) / (2 * sat_max)) * 100
82+
legend_labels = pd.DataFrame(
83+
[
84+
{"x": poor_mid, "y": -0.52, "text": "Poor"},
85+
{"x": satis_mid, "y": -0.52, "text": "Satisfactory"},
86+
{"x": good_mid, "y": -0.52, "text": "Good"},
87+
]
88+
)
7289

7390
# Plot - horizontal bullet charts (x is performance, y is metric category)
7491
plot = (
@@ -89,14 +106,22 @@
89106
color="#1a1a1a",
90107
size=2.5,
91108
)
92-
# Actual value labels at end of bars
109+
# Actual value labels above each bar
93110
+ geom_text(
94-
df_actual, aes(x="xmax + 3", y="y", label="actual"), ha="left", size=12, color="#306998", fontweight="bold"
111+
df_actual,
112+
aes(x="xmax", y="y + range_height/2 + 0.05", label="actual"),
113+
ha="right",
114+
va="bottom",
115+
size=10,
116+
color="#306998",
117+
fontweight="bold",
95118
)
119+
# Band meaning labels below the bottom metric
120+
+ geom_text(legend_labels, aes(x="x", y="y", label="text"), size=8, color="#555555", va="top")
96121
# Scale and labels
97-
+ scale_x_continuous(limits=(0, 115), breaks=[0, 25, 50, 75, 100], expand=(0, 0))
122+
+ scale_x_continuous(limits=(0, 100), breaks=[0, 25, 50, 75, 100], expand=(0, 0.02))
98123
+ scale_y_continuous(
99-
breaks=list(range(len(metrics))), labels=[m["label"] for m in reversed(metrics)], expand=(0.15, 0.15)
124+
breaks=list(range(len(metrics))), labels=[m["label"] for m in reversed(metrics)], expand=(0.25, 0.12)
100125
)
101126
+ labs(title="bullet-basic · plotnine · pyplots.ai", x="Performance (%)", y="")
102127
# Theme
@@ -110,8 +135,7 @@
110135
axis_text_y=element_text(size=18, ha="right"),
111136
panel_grid_major_y=element_blank(),
112137
panel_grid_minor=element_blank(),
113-
panel_grid_major_x=element_blank(),
114-
legend_position="none",
138+
panel_grid_major_x=element_line(color="#e0e0e0", size=0.3),
115139
)
116140
)
117141

plots/bullet-basic/metadata/plotnine.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
library: plotnine
22
specification_id: bullet-basic
33
created: '2025-12-23T09:19:04Z'
4-
updated: '2025-12-23T09:23:44Z'
5-
generated_by: claude-opus-4-5-20251101
4+
updated: '2026-02-22T12:00:00+00:00'
5+
generated_by: claude-opus-4-6
66
workflow_run: 20456606052
77
issue: 0
8-
python_version: 3.13.11
9-
library_version: 0.15.2
8+
python_version: 3.14.3
9+
library_version: 0.15.3
1010
preview_url: https://storage.googleapis.com/pyplots-images/plots/bullet-basic/plotnine/plot.png
1111
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bullet-basic/plotnine/plot_thumb.png
1212
preview_html: null
13-
quality_score: 94
13+
quality_score: null
1414
impl_tags:
1515
dependencies: []
1616
techniques:

0 commit comments

Comments
 (0)