Skip to content

Commit 07b8e8e

Browse files
feat(plotnine): implement bar-diverging (#6031)
## Implementation: `bar-diverging` - python/plotnine Implements the **python/plotnine** version of `bar-diverging`. **File:** `plots/bar-diverging/implementations/python/plotnine.py` **Parent Issue:** #2009 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25546578830)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 5b6acdd commit 07b8e8e

2 files changed

Lines changed: 203 additions & 164 deletions

File tree

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,46 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
bar-diverging: Diverging Bar Chart
3-
Library: plotnine 0.15.2 | Python 3.13.11
4-
Quality: 94/100 | Created: 2025-12-25
3+
Library: plotnine 0.15.4 | Python 3.13.13
4+
Quality: 91/100 | Updated: 2026-05-08
55
"""
66

7+
import importlib.util
8+
import os
9+
import sys
10+
711
import pandas as pd
8-
from plotnine import (
9-
aes,
10-
coord_flip,
11-
element_line,
12-
element_text,
13-
geom_bar,
14-
geom_hline,
15-
ggplot,
16-
labs,
17-
scale_fill_manual,
18-
theme,
19-
theme_minimal,
20-
)
2112

2213

14+
# Handle import conflicts: remove current dir and cache
15+
sys.path = [p for p in sys.path if not p.endswith("python")]
16+
if "plotnine" in sys.modules:
17+
del sys.modules["plotnine"]
18+
19+
# Import plotnine explicitly from site-packages
20+
plotnine_spec = importlib.util.find_spec("plotnine")
21+
plotnine = importlib.util.module_from_spec(plotnine_spec)
22+
sys.modules["plotnine"] = plotnine
23+
plotnine_spec.loader.exec_module(plotnine)
24+
25+
aes = plotnine.aes
26+
coord_flip = plotnine.coord_flip
27+
element_line = plotnine.element_line
28+
element_rect = plotnine.element_rect
29+
element_text = plotnine.element_text
30+
geom_bar = plotnine.geom_bar
31+
geom_hline = plotnine.geom_hline
32+
ggplot = plotnine.ggplot
33+
labs = plotnine.labs
34+
scale_fill_manual = plotnine.scale_fill_manual
35+
theme = plotnine.theme
36+
theme_minimal = plotnine.theme_minimal
37+
38+
THEME = os.getenv("ANYPLOT_THEME", "light")
39+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
40+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
41+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
42+
2343
# Data - Customer satisfaction survey across product categories
24-
# Net satisfaction score: % satisfied - % dissatisfied (range -100 to +100)
2544
categories = [
2645
"Mobile App",
2746
"Customer Service",
@@ -47,36 +66,37 @@
4766
# Create ordered categorical for proper sorting in plot
4867
df["category"] = pd.Categorical(df["category"], categories=df["category"], ordered=True)
4968

50-
# Color based on positive/negative
69+
# Color based on positive/negative (Okabe-Ito palette)
5170
df["sentiment"] = df["value"].apply(lambda x: "Positive" if x >= 0 else "Negative")
5271

5372
# Plot
5473
plot = (
5574
ggplot(df, aes(x="category", y="value", fill="sentiment"))
5675
+ geom_bar(stat="identity", width=0.7)
57-
+ geom_hline(yintercept=0, color="#333333", size=0.8)
76+
+ geom_hline(yintercept=0, color=INK_SOFT, size=0.8)
5877
+ coord_flip()
59-
+ scale_fill_manual(values={"Positive": "#306998", "Negative": "#E74C3C"})
78+
+ scale_fill_manual(values={"Positive": "#009E73", "Negative": "#D55E00"})
6079
+ labs(
6180
x="Product Category",
6281
y="Net Satisfaction Score (%)",
63-
title="bar-diverging · plotnine · pyplots.ai",
82+
title="bar-diverging · plotnine · anyplot.ai",
6483
fill="Sentiment",
6584
)
6685
+ theme_minimal()
6786
+ theme(
87+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
88+
panel_background=element_rect(fill=PAGE_BG),
89+
panel_grid_major_y=element_line(color=INK, size=0.3, alpha=0.10),
90+
panel_grid_minor=element_line(color=INK, size=0.2, alpha=0.05),
91+
axis_title=element_text(color=INK, size=20),
92+
axis_text=element_text(color=INK_SOFT, size=16),
93+
plot_title=element_text(color=INK, size=24),
94+
legend_background=element_rect(fill=PAGE_BG, color=INK_SOFT),
95+
legend_text=element_text(color=INK_SOFT, size=16),
96+
legend_title=element_text(color=INK, size=18),
6897
figure_size=(16, 9),
69-
text=element_text(size=14),
70-
axis_title=element_text(size=20),
71-
axis_text=element_text(size=16),
72-
plot_title=element_text(size=24, ha="center"),
73-
legend_text=element_text(size=16),
74-
legend_title=element_text(size=18),
75-
legend_position="right",
76-
panel_grid_major_y=element_line(alpha=0.3),
77-
panel_grid_minor=element_line(alpha=0),
7898
)
7999
)
80100

81101
# Save
82-
plot.save("plot.png", dpi=300, verbose=False)
102+
plot.save(f"plot-{THEME}.png", dpi=300, verbose=False)

0 commit comments

Comments
 (0)