{"spec_id":"bar-3d-categorical","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nbar-3d-categorical: 3D Bar Chart for Categorical Comparison\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 81/100 | Created: 2026-05-15\n\"\"\"\n\nimport os\nimport sys\n\n\n_here = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p or os.getcwd()) != _here]\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\n\n\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\"\n\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\"]\n\n# Data — survey satisfaction scores across age groups and education levels\nnp.random.seed(42)\n\nage_groups = [\"18–24\", \"25–34\", \"35–44\", \"45–54\", \"55–64\"]\neducation_levels = [\"High School\", \"Bachelor's\", \"Master's\", \"Doctorate\"]\n\nrows = []\nbase_scores = {\n    \"High School\": [62, 68, 71, 74, 70],\n    \"Bachelor's\": [70, 75, 78, 76, 73],\n    \"Master's\": [74, 79, 82, 80, 77],\n    \"Doctorate\": [76, 81, 85, 83, 79],\n}\nfor edu, scores in base_scores.items():\n    for age, score in zip(age_groups, scores, strict=True):\n        jitter = np.random.uniform(-1.5, 1.5)\n        rows.append({\"Age Group\": age, \"Education\": edu, \"Satisfaction Score\": round(score + jitter, 1)})\n\ndf = pd.DataFrame(rows)\n\n# Plot\nchart = (\n    alt.Chart(df)\n    .mark_bar(cornerRadiusTopLeft=4, cornerRadiusTopRight=4)\n    .encode(\n        x=alt.X(\n            \"Age Group:N\",\n            sort=age_groups,\n            title=\"Age Group\",\n            axis=alt.Axis(labelAngle=0, labelFontSize=18, titleFontSize=22),\n        ),\n        y=alt.Y(\n            \"Satisfaction Score:Q\",\n            title=\"Satisfaction Score\",\n            scale=alt.Scale(domain=[0, 100]),\n            axis=alt.Axis(labelFontSize=18, titleFontSize=22, grid=True),\n        ),\n        color=alt.Color(\n            \"Education:N\",\n            sort=education_levels,\n            scale=alt.Scale(domain=education_levels, range=IMPRINT),\n            legend=alt.Legend(title=\"Education Level\", titleFontSize=18, labelFontSize=16, orient=\"top-right\"),\n        ),\n        xOffset=alt.XOffset(\"Education:N\", sort=education_levels),\n        tooltip=[\n            alt.Tooltip(\"Age Group:N\"),\n            alt.Tooltip(\"Education:N\"),\n            alt.Tooltip(\"Satisfaction Score:Q\", format=\".1f\"),\n        ],\n    )\n    .properties(\n        width=1600,\n        height=860,\n        title=alt.Title(\"bar-3d-categorical · altair · anyplot.ai\", fontSize=28, color=INK, anchor=\"start\", offset=16),\n        background=PAGE_BG,\n    )\n    .configure_view(fill=PAGE_BG, stroke=None)\n    .configure_axis(\n        domainColor=INK_SOFT, tickColor=INK_SOFT, gridColor=INK, gridOpacity=0.10, labelColor=INK_SOFT, titleColor=INK\n    )\n    .configure_legend(fillColor=ELEVATED_BG, strokeColor=INK_SOFT, labelColor=INK_SOFT, titleColor=INK, padding=10)\n)\n\n# Save\nchart.save(f\"plot-{THEME}.png\", scale_factor=3.0)\nchart.save(f\"plot-{THEME}.html\")\n"}