{"spec_id":"bar-feature-importance","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nbar-feature-importance: Feature Importance Bar Chart\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 96/100 | Updated: 2026-05-10\n\"\"\"\n\nimport os\n\nimport altair as alt\nimport numpy as np\nimport pandas as pd\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\"\n\n# Data - Feature importances from a hypothetical RandomForest model\nnp.random.seed(42)\n\nfeatures = [\n    \"customer_lifetime_value\",\n    \"purchase_frequency\",\n    \"avg_order_value\",\n    \"days_since_last_purchase\",\n    \"total_purchases\",\n    \"account_age_months\",\n    \"email_open_rate\",\n    \"website_visits\",\n    \"support_tickets\",\n    \"referral_count\",\n    \"cart_abandonment_rate\",\n    \"discount_usage\",\n    \"mobile_app_usage\",\n    \"newsletter_subscribed\",\n    \"social_media_engagement\",\n]\n\n# Realistic importance scores (sum to ~1.0 for tree-based models)\nimportances = np.array(\n    [0.182, 0.156, 0.134, 0.098, 0.087, 0.072, 0.058, 0.051, 0.042, 0.038, 0.031, 0.022, 0.015, 0.009, 0.005]\n)\n\n# Standard deviations for ensemble variability\nstds = importances * np.random.uniform(0.15, 0.35, len(importances))\n\ndf = pd.DataFrame({\"feature\": features, \"importance\": importances, \"std\": stds})\n\n# Sort by importance for display\ndf = df.sort_values(\"importance\", ascending=True).reset_index(drop=True)\n\n# Create base chart\nbase = alt.Chart(df).encode(\n    y=alt.Y(\"feature:N\", sort=None, title=\"Feature\", axis=alt.Axis(labelFontSize=18, titleFontSize=22, labelLimit=300)),\n    x=alt.X(\"importance:Q\", title=\"Importance Score\", axis=alt.Axis(labelFontSize=18, titleFontSize=22)),\n    tooltip=[\n        alt.Tooltip(\"feature:N\", title=\"Feature\"),\n        alt.Tooltip(\"importance:Q\", title=\"Importance\", format=\".3f\"),\n        alt.Tooltip(\"std:Q\", title=\"Std Dev\", format=\".3f\"),\n    ],\n)\n\n# Bars with color gradient based on importance using viridis (continuous sequential)\nbars = base.mark_bar(size=30).encode(color=alt.Color(\"importance:Q\", scale=alt.Scale(scheme=\"viridis\"), legend=None))\n\n# Error bars\nerror_bars = (\n    base.mark_errorbar(color=INK_SOFT, thickness=2)\n    .encode(x=alt.X(\"x_min:Q\", title=\"\"), x2=\"x_max:Q\")\n    .transform_calculate(x_min=\"datum.importance - datum.std\", x_max=\"datum.importance + datum.std\")\n)\n\n# Text labels at end of bars\ntext = (\n    base.mark_text(align=\"left\", baseline=\"middle\", dx=5, fontSize=16, fontWeight=\"bold\", color=INK)\n    .encode(text=alt.Text(\"importance:Q\", format=\".3f\"), x=alt.X(\"text_x:Q\"))\n    .transform_calculate(text_x=\"datum.importance + datum.std + 0.005\")\n)\n\n# Combine layers\nchart = (\n    (bars + error_bars + text)\n    .properties(\n        width=1600,\n        height=900,\n        background=PAGE_BG,\n        title=alt.Title(\n            \"bar-feature-importance · altair · anyplot.ai\", fontSize=28, anchor=\"start\", offset=20, color=INK\n        ),\n    )\n    .configure_axis(\n        domainColor=INK_SOFT,\n        tickColor=INK_SOFT,\n        labelColor=INK_SOFT,\n        titleColor=INK,\n        gridColor=INK,\n        gridOpacity=0.10,\n        labelFontSize=18,\n        titleFontSize=22,\n    )\n    .configure_view(fill=PAGE_BG, stroke=INK_SOFT)\n    .configure_legend(fillColor=ELEVATED_BG, strokeColor=INK_SOFT, labelColor=INK_SOFT, titleColor=INK)\n)\n\n# Save output\nchart.save(f\"plot-{THEME}.png\", scale_factor=3.0)\nchart.save(f\"plot-{THEME}.html\")\n"}