{"spec_id":"bar-permutation-importance","library":"makie","language":"julia","code":"# anyplot.ai\n# bar-permutation-importance: Permutation Feature Importance Plot\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 92/100 | Created: 2026-08-26\n\nusing CairoMakie\nusing Colors\nusing Random\n\nRandom.seed!(42)\n\n# --- Theme tokens -----------------------------------------------------------\nconst THEME    = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG  = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\n\n# Imprint sequential colormap — single-polarity continuous data\nconst ANYPLOT_SEQ = cgrad([colorant\"#009E73\", colorant\"#4467A3\"])\n\n# --- Data: permutation importance for a churn-prediction gradient-boosting model\nfeatures = [\n    \"monthly_charges\", \"tenure_months\", \"contract_type\", \"total_charges\",\n    \"num_support_tickets\", \"internet_service\", \"payment_method\",\n    \"avg_data_usage_gb\", \"customer_age\", \"paperless_billing\",\n    \"has_multiple_lines\", \"senior_citizen\", \"partner_status\", \"dependents_count\",\n]\nimportance_mean = [\n    0.182, 0.146, 0.098, 0.081, 0.063, 0.047, 0.038,\n    0.029, 0.021, 0.014, 0.009, 0.005, 0.002, -0.004,\n]\nimportance_std = 0.10 .* abs.(importance_mean) .+ 0.004 .* rand(length(features))\n\nn = length(features)\ny_positions = collect(n:-1:1)  # highest importance at the top\n\n# --- Plot ---------------------------------------------------------------\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"bar-permutation-importance · julia · makie · anyplot.ai\",\n    titlesize          = 20,\n    titlecolor         = INK,\n    xlabel             = \"Decrease in Accuracy When Feature Is Shuffled\",\n    xlabelsize         = 14,\n    xlabelcolor        = INK,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xtickcolor         = INK_SOFT,\n    ytickcolor         = INK_SOFT,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    ygridvisible       = false,\n    yticks             = (1:n, reverse(features)),\n)\n\nvlines!(ax, 0; color = INK_SOFT, linewidth = 1.5, linestyle = :dash)\n\nbarplot!(\n    ax, y_positions, importance_mean;\n    direction = :x,\n    color = importance_mean,\n    colormap = ANYPLOT_SEQ,\n    colorrange = (minimum(importance_mean), maximum(importance_mean)),\n    strokewidth = 0,\n)\n\nerrorbars!(\n    ax, importance_mean, y_positions, importance_std;\n    direction = :x,\n    color = INK_SOFT,\n    whiskerwidth = 8,\n    linewidth = 1.5,\n)\n\nColorbar(\n    fig[1, 2];\n    limits = (minimum(importance_mean), maximum(importance_mean)),\n    colormap = ANYPLOT_SEQ,\n    label = \"Importance\",\n    labelcolor = INK,\n    labelsize = 12,\n    ticklabelsize = 11,\n    ticklabelcolor = INK_SOFT,\n    tickcolor = INK_SOFT,\n)\ncolsize!(fig.layout, 2, Relative(0.03))\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}