{"spec_id":"bar-permutation-importance","library":"bokeh","language":"python","code":"\"\"\" anyplot.ai\nbar-permutation-importance: Permutation Feature Importance Plot\nLibrary: bokeh 3.9.0 | Python 3.13.13\nQuality: 85/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\nimport sys\nimport time\nfrom pathlib import Path\n\nimport numpy as np\n\n\n# Workaround for bokeh.py shadowing: clear current dir from sys.path and inject site-packages at beginning\n_site_packages = next((p for p in sys.path if \"site-packages\" in p), None)\nsys.path = [p for p in sys.path if not (p == \"\" or p == \".\" or \"site-packages\" in p)]\nif _site_packages:\n    sys.path.insert(0, _site_packages)\n\n\ndef main():\n    \"\"\"Main implementation function to avoid module name shadowing.\"\"\"\n    from bokeh.io import output_file, save\n    from bokeh.models import ColumnDataSource, HoverTool, Whisker\n    from bokeh.palettes import Cividis256\n    from bokeh.plotting import figure\n    from bokeh.transform import linear_cmap\n    from selenium import webdriver\n    from selenium.webdriver.chrome.options import Options\n\n    # Theme tokens\n    THEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n    PAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\n    INK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\n    INK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n    # Data: Simulated permutation importance results\n    np.random.seed(42)\n\n    features = [\n        \"Square Footage\",\n        \"Number of Bedrooms\",\n        \"Neighborhood Score\",\n        \"Year Built\",\n        \"Lot Size\",\n        \"Distance to City Center\",\n        \"Number of Bathrooms\",\n        \"Garage Capacity\",\n        \"School Rating\",\n        \"Crime Index\",\n        \"Property Tax Rate\",\n        \"Previous Sale Price\",\n        \"Days on Market\",\n        \"Walk Score\",\n        \"Public Transit Access\",\n    ]\n\n    # Generate importance values (higher = more important)\n    importance_mean = np.array(\n        [0.182, 0.145, 0.128, 0.095, 0.078, 0.065, 0.052, 0.041, 0.035, 0.028, 0.018, 0.012, 0.005, -0.003, -0.008]\n    )\n\n    # Standard deviations (variability across shuffles)\n    importance_std = np.array(\n        [0.025, 0.022, 0.020, 0.018, 0.015, 0.014, 0.012, 0.011, 0.010, 0.009, 0.008, 0.007, 0.006, 0.005, 0.004]\n    )\n\n    # Sort by importance (highest first)\n    sort_idx = np.argsort(importance_mean)[::-1]\n    features_sorted = [features[i] for i in sort_idx]\n    importance_mean_sorted = importance_mean[sort_idx]\n    importance_std_sorted = importance_std[sort_idx]\n\n    # Reverse for plotting (highest at top)\n    features_plot = features_sorted[::-1]\n    importance_mean_plot = importance_mean_sorted[::-1]\n    importance_std_plot = importance_std_sorted[::-1]\n\n    # Create data source\n    source = ColumnDataSource(\n        data={\n            \"features\": features_plot,\n            \"importance\": importance_mean_plot,\n            \"std\": importance_std_plot,\n            \"upper\": importance_mean_plot + importance_std_plot,\n            \"lower\": importance_mean_plot - importance_std_plot,\n        }\n    )\n\n    # Create figure with categorical y-axis\n    p = figure(\n        width=4800,\n        height=2700,\n        y_range=features_plot,\n        x_axis_label=\"Mean Decrease in Model Score\",\n        title=\"bar-permutation-importance · bokeh · anyplot.ai\",\n    )\n\n    # Color mapper for bars (darker = more important)\n    mapper = linear_cmap(\n        field_name=\"importance\", palette=Cividis256, low=min(importance_mean_plot), high=max(importance_mean_plot)\n    )\n\n    # Draw horizontal bars\n    p.hbar(\n        y=\"features\",\n        right=\"importance\",\n        left=0,\n        height=0.7,\n        source=source,\n        fill_color=mapper,\n        line_color=INK_SOFT,\n        line_width=1,\n    )\n\n    # Add error bars (whiskers)\n    whisker = Whisker(\n        source=source,\n        base=\"features\",\n        upper=\"upper\",\n        lower=\"lower\",\n        dimension=\"width\",\n        line_color=INK_SOFT,\n        line_width=2,\n        upper_head=None,\n        lower_head=None,\n    )\n    p.add_layout(whisker)\n\n    # Add vertical reference line at x=0\n    p.line(x=[0, 0], y=[-1, len(features_plot)], line_color=INK_SOFT, line_width=2, line_dash=\"dashed\")\n\n    # Add hover tool\n    hover = HoverTool(\n        tooltips=[(\"Feature\", \"@features\"), (\"Importance\", \"@importance{0.000}\"), (\"Std Dev\", \"@std{0.000}\")]\n    )\n    p.add_tools(hover)\n\n    # Styling\n    p.title.text_font_size = \"28pt\"\n    p.title.text_font_style = \"bold\"\n    p.title.text_color = INK\n    p.xaxis.axis_label_text_font_size = \"22pt\"\n    p.yaxis.axis_label_text_font_size = \"22pt\"\n    p.xaxis.axis_label_text_color = INK\n    p.yaxis.axis_label_text_color = INK\n    p.xaxis.major_label_text_font_size = \"18pt\"\n    p.yaxis.major_label_text_font_size = \"18pt\"\n    p.xaxis.major_label_text_color = INK_SOFT\n    p.yaxis.major_label_text_color = INK_SOFT\n\n    # Grid styling\n    p.xgrid.grid_line_color = INK\n    p.xgrid.grid_line_alpha = 0.10\n    p.ygrid.grid_line_color = None\n\n    # Axis styling\n    p.xaxis.axis_line_color = INK_SOFT\n    p.yaxis.axis_line_color = INK_SOFT\n    p.xaxis.axis_line_width = 1\n    p.yaxis.axis_line_width = 1\n    p.outline_line_color = INK_SOFT\n    p.outline_line_width = 1\n\n    # Background\n    p.background_fill_color = PAGE_BG\n    p.border_fill_color = PAGE_BG\n\n    # Save HTML\n    output_file(f\"plot-{THEME}.html\")\n    save(p)\n\n    # Screenshot with headless Chrome using Selenium\n    W, H = 4800, 2700\n    opts = Options()\n    for arg in (\n        \"--headless=new\",\n        \"--no-sandbox\",\n        \"--disable-dev-shm-usage\",\n        \"--disable-gpu\",\n        f\"--window-size={W},{H}\",\n        \"--hide-scrollbars\",\n    ):\n        opts.add_argument(arg)\n    driver = webdriver.Chrome(options=opts)\n    driver.set_window_size(W, H)\n    driver.get(f\"file://{Path(f'plot-{THEME}.html').resolve()}\")\n    time.sleep(3)\n    driver.save_screenshot(f\"plot-{THEME}.png\")\n    driver.quit()\n\n\nif __name__ == \"__main__\":\n    main()\n"}