{"spec_id":"bar-3d-categorical","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nbar-3d-categorical: 3D Bar Chart for Categorical Comparison\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 85/100 | Created: 2026-05-15\n\"\"\"\n\nimport os\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\n\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Data — quarterly unit sales (thousands) by product category and region\nnp.random.seed(42)\n\nproducts = [\"Laptops\", \"Tablets\", \"Phones\", \"Monitors\"]\nregions = [\"North\", \"South\", \"East\", \"West\"]\nn_prod = len(products)\nn_reg = len(regions)\n\nsales_base = np.array(\n    [[45.2, 31.8, 38.5, 27.9], [22.1, 18.4, 25.3, 20.1], [68.7, 55.2, 72.1, 60.8], [15.3, 11.9, 18.2, 13.7]]\n)\nsales = sales_base + np.random.normal(0, 1.2, (n_prod, n_reg))\n\n# Plot\nfig = plt.figure(figsize=(16, 9), facecolor=PAGE_BG)\nax = fig.add_subplot(111, projection=\"3d\")\n\nbar_w = 0.55\nbar_d = 0.55\n\nfor i, (_product, color) in enumerate(zip(products, IMPRINT, strict=False)):\n    for j in range(n_reg):\n        h = sales[i, j]\n        ax.bar3d(i - bar_w / 2, j - bar_d / 2, 0, bar_w, bar_d, h, color=color, alpha=0.85, shade=True)\n        ax.text(i, j, h + 1.5, f\"{h:.0f}\", ha=\"center\", va=\"bottom\", fontsize=11, color=INK, fontweight=\"medium\")\n\n# Style — axis ticks and labels\nax.set_xticks(range(n_prod))\nax.set_xticklabels(products, fontsize=14)\nax.set_yticks(range(n_reg))\nax.set_yticklabels(regions, fontsize=14)\nax.tick_params(axis=\"x\", colors=INK_SOFT, pad=6)\nax.tick_params(axis=\"y\", colors=INK_SOFT, pad=6)\nax.tick_params(axis=\"z\", labelsize=14, colors=INK_SOFT)\n\nax.set_xlabel(\"Product Category\", fontsize=18, color=INK, labelpad=18)\nax.set_ylabel(\"Region\", fontsize=18, color=INK, labelpad=18)\nax.set_zlabel(\"Units Sold (thousands)\", fontsize=18, color=INK, labelpad=12)\n\nax.set_title(\"bar-3d-categorical · seaborn · anyplot.ai\", fontsize=22, fontweight=\"medium\", color=INK, pad=22)\n\nax.view_init(elev=30, azim=45)\n\n# Pane backgrounds — transparent with subtle edges\nfor pane in (ax.xaxis.pane, ax.yaxis.pane, ax.zaxis.pane):\n    pane.fill = False\n    pane.set_edgecolor(INK_SOFT)\n    pane.set_alpha(0.25)\n\n# Legend\npatches = [mpatches.Patch(color=IMPRINT[i], label=p) for i, p in enumerate(products)]\nlegend = ax.legend(\n    handles=patches,\n    loc=\"upper left\",\n    fontsize=14,\n    title=\"Product\",\n    title_fontsize=15,\n    facecolor=ELEVATED_BG,\n    edgecolor=INK_SOFT,\n    labelcolor=INK_SOFT,\n)\nlegend.get_title().set_color(INK)\n\n# Save\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}