|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | bar-stacked: Stacked Bar Chart |
3 | | -Library: seaborn 0.13.2 | Python 3.13.11 |
4 | | -Quality: 91/100 | Created: 2025-12-26 |
| 3 | +Library: seaborn 0.13.2 | Python 3.13.13 |
| 4 | +Quality: 84/100 | Updated: 2026-05-09 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import matplotlib.pyplot as plt |
| 10 | +import numpy as np |
8 | 11 | import pandas as pd |
9 | 12 | import seaborn as sns |
10 | 13 |
|
11 | 14 |
|
12 | | -# Data - Monthly sales by product category (realistic business scenario) |
| 15 | +# Theme tokens |
| 16 | +THEME = os.getenv("ANYPLOT_THEME", "light") |
| 17 | +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" |
| 18 | +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" |
| 19 | +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
| 20 | +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
| 21 | + |
| 22 | +# Okabe-Ito palette (first series always #009E73) |
| 23 | +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7"] |
| 24 | + |
| 25 | +# Data - Monthly sales by product category |
| 26 | +np.random.seed(42) |
13 | 27 | categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] |
14 | 28 | products = ["Electronics", "Clothing", "Home & Garden", "Sports"] |
15 | 29 |
|
16 | | -# Create realistic sales data (in thousands) |
17 | 30 | data = { |
18 | 31 | "Month": categories * len(products), |
19 | 32 | "Product": [p for p in products for _ in categories], |
|
58 | 71 | ordered_products = product_totals.index.tolist() |
59 | 72 | df["Product"] = pd.Categorical(df["Product"], categories=ordered_products, ordered=True) |
60 | 73 |
|
61 | | -# Create plot with seaborn styling |
62 | | -sns.set_style("whitegrid") |
| 74 | +# Set theme and styling |
| 75 | +sns.set_theme( |
| 76 | + style="ticks", |
| 77 | + rc={ |
| 78 | + "figure.facecolor": PAGE_BG, |
| 79 | + "axes.facecolor": PAGE_BG, |
| 80 | + "axes.edgecolor": INK_SOFT, |
| 81 | + "axes.labelcolor": INK, |
| 82 | + "text.color": INK, |
| 83 | + "xtick.color": INK_SOFT, |
| 84 | + "ytick.color": INK_SOFT, |
| 85 | + "grid.color": INK, |
| 86 | + "grid.alpha": 0.10, |
| 87 | + "legend.facecolor": ELEVATED_BG, |
| 88 | + "legend.edgecolor": INK_SOFT, |
| 89 | + }, |
| 90 | +) |
63 | 91 | sns.set_context("talk", font_scale=1.2) |
64 | 92 |
|
65 | | -fig, ax = plt.subplots(figsize=(16, 9)) |
| 93 | +fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG) |
66 | 94 |
|
67 | | -# Python-themed color palette with distinct colors (avoiding similar yellows) |
68 | | -# Map colors to original product order, then reorder based on totals |
69 | | -original_colors = { |
70 | | - "Electronics": "#306998", # Python Blue |
71 | | - "Clothing": "#FFD43B", # Python Yellow |
72 | | - "Home & Garden": "#4B8BBE", # Light Blue |
73 | | - "Sports": "#E57373", # Coral/Salmon for contrast |
74 | | -} |
75 | | -colors = [original_colors[p] for p in ordered_products] |
| 95 | +# Create color map for products |
| 96 | +product_colors = {p: OKABE_ITO[i] for i, p in enumerate(ordered_products)} |
| 97 | +colors = [product_colors[p] for p in ordered_products] |
76 | 98 |
|
77 | | -# Use seaborn's histplot with weights for stacked bar chart |
78 | | -# This is seaborn's native approach for stacked categorical bars |
| 99 | +# Plot stacked bar chart using histplot |
79 | 100 | sns.histplot( |
80 | 101 | data=df, |
81 | 102 | x="Month", |
|
84 | 105 | multiple="stack", |
85 | 106 | palette=colors, |
86 | 107 | shrink=0.7, |
87 | | - edgecolor="white", |
| 108 | + edgecolor=PAGE_BG, |
88 | 109 | linewidth=1.5, |
89 | 110 | ax=ax, |
90 | 111 | ) |
91 | 112 |
|
92 | 113 | # Calculate totals for labels on top of stacks |
93 | 114 | totals = df.groupby("Month", observed=True)["Sales"].sum() |
94 | 115 | for i, (_month, total) in enumerate(totals.items()): |
95 | | - ax.text(i, total + 8, f"${int(total)}K", ha="center", va="bottom", fontsize=16, fontweight="bold") |
| 116 | + ax.text(i, total + 8, f"${int(total)}K", ha="center", va="bottom", fontsize=16, fontweight="bold", color=INK) |
96 | 117 |
|
97 | 118 | # Styling |
98 | | -ax.set_xlabel("Month", fontsize=20) |
99 | | -ax.set_ylabel("Sales (Thousands $)", fontsize=20) |
100 | | -ax.set_title("bar-stacked · seaborn · pyplots.ai", fontsize=24, fontweight="bold") |
101 | | -ax.tick_params(axis="both", labelsize=16) |
| 119 | +ax.set_xlabel("Month", fontsize=20, color=INK) |
| 120 | +ax.set_ylabel("Sales (Thousands $)", fontsize=20, color=INK) |
| 121 | +ax.set_title("bar-stacked · seaborn · anyplot.ai", fontsize=24, fontweight="bold", color=INK) |
| 122 | +ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT) |
102 | 123 |
|
103 | | -# Legend - move to right and adjust styling |
| 124 | +# Legend |
104 | 125 | legend = ax.get_legend() |
105 | 126 | legend.set_title("Product Category") |
106 | 127 | legend.get_title().set_fontsize(18) |
| 128 | +legend.get_title().set_color(INK) |
107 | 129 | for text in legend.get_texts(): |
108 | 130 | text.set_fontsize(16) |
| 131 | + text.set_color(INK) |
109 | 132 | legend.set_bbox_to_anchor((1.02, 1)) |
110 | 133 | legend.set_loc("upper left") |
111 | | -legend.get_frame().set_edgecolor("gray") |
| 134 | +legend.get_frame().set_facecolor(ELEVATED_BG) |
| 135 | +legend.get_frame().set_edgecolor(INK_SOFT) |
112 | 136 |
|
113 | 137 | # Grid styling |
114 | | -ax.yaxis.grid(True, alpha=0.3, linestyle="--") |
| 138 | +ax.yaxis.grid(True, alpha=0.10, linewidth=0.8) |
115 | 139 | ax.xaxis.grid(False) |
116 | 140 | ax.set_axisbelow(True) |
117 | 141 |
|
118 | | -# Remove top and right spines |
119 | | -sns.despine() |
| 142 | +# Spine styling |
| 143 | +for spine in ["top", "right"]: |
| 144 | + ax.spines[spine].set_visible(False) |
| 145 | +for spine in ["left", "bottom"]: |
| 146 | + ax.spines[spine].set_color(INK_SOFT) |
120 | 147 |
|
121 | 148 | # Adjust y-axis to accommodate total labels |
122 | 149 | ax.set_ylim(0, totals.max() * 1.15) |
123 | 150 |
|
124 | 151 | plt.tight_layout() |
125 | | -plt.savefig("plot.png", dpi=300, bbox_inches="tight") |
| 152 | +plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) |
0 commit comments