{"spec_id":"bar-permutation-importance","library":"altair","language":"python","code":"\"\"\" anyplot.ai\nbar-permutation-importance: Permutation Feature Importance Plot\nLibrary: altair 6.1.0 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\nimport sys\n\n\n# Work around local file shadowing the altair package\nscript_dir = os.path.dirname(os.path.abspath(__file__))\nif script_dir in sys.path:\n    sys.path.remove(script_dir)\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 - Simulate permutation importance results from a ML model\nnp.random.seed(42)\n\n# Feature names (typical ML features for a housing price model)\nfeatures = [\n    \"Location Score\",\n    \"Square Footage\",\n    \"Number of Bedrooms\",\n    \"Year Built\",\n    \"Lot Size\",\n    \"Garage Capacity\",\n    \"Bathroom Count\",\n    \"Distance to Transit\",\n    \"School Rating\",\n    \"Crime Index\",\n    \"Property Tax Rate\",\n    \"HOA Fees\",\n    \"Energy Rating\",\n    \"Basement Area\",\n    \"Pool Presence\",\n]\n\n# Generate realistic importance values (some high, some medium, some low/negative)\nimportance_mean = np.array(\n    [0.142, 0.128, 0.089, 0.072, 0.058, 0.045, 0.038, 0.032, 0.028, 0.022, 0.015, 0.008, 0.005, -0.002, -0.008]\n)\n\n# Standard deviations (higher for more important features, showing variability)\nimportance_std = np.array(\n    [0.018, 0.015, 0.012, 0.010, 0.009, 0.008, 0.007, 0.006, 0.006, 0.005, 0.004, 0.003, 0.003, 0.002, 0.003]\n)\n\n# Create DataFrame\ndf = pd.DataFrame({\"feature\": features, \"importance_mean\": importance_mean, \"importance_std\": importance_std})\n\n# Sort by importance (ascending) for bottom-to-top display\ndf = df.sort_values(\"importance_mean\", ascending=True).reset_index(drop=True)\n\n# Calculate error bar positions\ndf[\"error_min\"] = df[\"importance_mean\"] - df[\"importance_std\"]\ndf[\"error_max\"] = df[\"importance_mean\"] + df[\"importance_std\"]\n\n# Base chart for bars with color gradient based on importance (viridis for perceptual uniformity)\nbars = (\n    alt.Chart(df)\n    .mark_bar(size=30)\n    .encode(\n        x=alt.X(\n            \"importance_mean:Q\",\n            title=\"Mean Decrease in Model Score\",\n            axis=alt.Axis(labelFontSize=18, titleFontSize=22, titlePadding=15),\n        ),\n        y=alt.Y(\n            \"feature:N\",\n            sort=alt.EncodingSortField(field=\"importance_mean\", order=\"descending\"),\n            title=\"Feature\",\n            axis=alt.Axis(labelFontSize=16, titleFontSize=22, titlePadding=15),\n        ),\n        color=alt.Color(\"importance_mean:Q\", scale=alt.Scale(scheme=\"viridis\", domain=[-0.01, 0.15]), legend=None),\n        tooltip=[\n            alt.Tooltip(\"feature:N\", title=\"Feature\"),\n            alt.Tooltip(\"importance_mean:Q\", title=\"Mean Importance\", format=\".4f\"),\n            alt.Tooltip(\"importance_std:Q\", title=\"Std Dev\", format=\".4f\"),\n        ],\n    )\n)\n\n# Error bars with theme-adaptive color\nerror_bars = (\n    alt.Chart(df)\n    .mark_errorbar(color=INK_SOFT, thickness=2.5)\n    .encode(\n        x=alt.X(\"error_min:Q\", title=\"\"),\n        x2=\"error_max:Q\",\n        y=alt.Y(\"feature:N\", sort=alt.EncodingSortField(field=\"importance_mean\", order=\"descending\")),\n    )\n)\n\n# Vertical reference line at x=0\nzero_line = (\n    alt.Chart(pd.DataFrame({\"x\": [0]})).mark_rule(color=INK_SOFT, strokeWidth=2, strokeDash=[4, 4]).encode(x=\"x:Q\")\n)\n\n# Combine layers with grid and interactivity\nchart = (\n    alt.layer(zero_line, bars, error_bars)\n    .properties(\n        width=1600,\n        height=900,\n        background=PAGE_BG,\n        title=alt.Title(\"bar-permutation-importance · altair · anyplot.ai\", fontSize=28, anchor=\"middle\", offset=20),\n    )\n    .interactive()\n    .configure_view(fill=PAGE_BG, stroke=INK_SOFT, strokeWidth=0)\n    .configure_axis(\n        domainColor=INK_SOFT,\n        tickColor=INK_SOFT,\n        gridColor=INK_SOFT,\n        gridOpacity=0.15,\n        labelColor=INK_SOFT,\n        titleColor=INK,\n    )\n    .configure_title(color=INK, fontSize=28)\n    .configure_legend(fillColor=ELEVATED_BG, strokeColor=INK_SOFT, labelColor=INK_SOFT, titleColor=INK)\n)\n\n# Save as PNG and HTML with theme-suffixed filenames\nchart.save(f\"plot-{THEME}.png\", scale_factor=3.0)\nchart.save(f\"plot-{THEME}.html\")\n"}