{"spec_id":"bar-feature-importance","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// bar-feature-importance: Feature Importance Bar Chart\n// Library: chartjs 4.4.7 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-09-02\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Feature importances from a gradient-boosted model predicting house sale\n// price (King County-style housing data), sorted descending so the highest\n// importance renders at the top -- Chart.js horizontal bars (indexAxis: \"y\")\n// place labels[0] at the top by default.\nconst features = [\n  { name: \"Waterfront view\", importance: 0.012 },\n  { name: \"Renovation year\", importance: 0.015 },\n  { name: \"Condition rating\", importance: 0.018 },\n  { name: \"Number of floors\", importance: 0.021 },\n  { name: \"Bedroom count\", importance: 0.027 },\n  { name: \"Basement area (sqft)\", importance: 0.033 },\n  { name: \"Zip code\", importance: 0.041 },\n  { name: \"Bathroom count\", importance: 0.048 },\n  { name: \"Year built\", importance: 0.056 },\n  { name: \"View quality score\", importance: 0.064 },\n  { name: \"Latitude\", importance: 0.079 },\n  { name: \"Above-ground area (sqft)\", importance: 0.101 },\n  { name: \"Construction grade\", importance: 0.138 },\n  { name: \"Living area (sqft)\", importance: 0.187 },\n].sort((a, b) => b.importance - a.importance);\n\nconst labels = features.map((f) => f.name);\nconst values = features.map((f) => f.importance);\nconst minValue = Math.min(...values);\nconst maxValue = Math.max(...values);\n\n// --- Sequential gradient (Imprint imprint_seq) — low to high importance ----\nfunction hexToRgb(hex) {\n  const n = parseInt(hex.slice(1), 16);\n  return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\nfunction lerpColor(hexLow, hexHigh, ratio) {\n  const [r1, g1, b1] = hexToRgb(hexLow);\n  const [r2, g2, b2] = hexToRgb(hexHigh);\n  const r = Math.round(r1 + (r2 - r1) * ratio);\n  const g = Math.round(g1 + (g2 - g1) * ratio);\n  const b = Math.round(b1 + (b2 - b1) * ratio);\n  return `rgb(${r}, ${g}, ${b})`;\n}\nconst barColors = values.map((v) => {\n  const ratio = (v - minValue) / (maxValue - minValue);\n  return lerpColor(t.seq[0], t.seq[1], ratio);\n});\n\n// Subtle emphasis on the single most important feature (index 0, now at the\n// top after the descending sort) to sharpen the \"what matters most\" story.\nconst borderWidths = values.map((_, i) => (i === 0 ? 2 : 0));\nconst borderColors = values.map((_, i) => (i === 0 ? t.ink : \"transparent\"));\n\n// --- Value labels at bar end (native Chart.js plugin API, no external deps) -\nconst valueLabelsPlugin = {\n  id: \"valueLabels\",\n  afterDatasetsDraw(chart) {\n    const { ctx } = chart;\n    const meta = chart.getDatasetMeta(0);\n    ctx.save();\n    ctx.fillStyle = t.ink;\n    ctx.textBaseline = \"middle\";\n    ctx.textAlign = \"left\";\n    meta.data.forEach((bar, i) => {\n      ctx.font = i === 0 ? \"700 15px sans-serif\" : \"500 15px sans-serif\";\n      ctx.fillText(values[i].toFixed(3), bar.x + 10, bar.y);\n    });\n    ctx.restore();\n  },\n};\n\n// --- Mount -------------------------------------------------------------------\nconst canvas = document.createElement(\"canvas\");\ndocument.getElementById(\"container\").appendChild(canvas);\n\n// --- Chart ---------------------------------------------------------------\nnew Chart(canvas, {\n  type: \"bar\",\n  data: {\n    labels,\n    datasets: [\n      {\n        label: \"Feature importance\",\n        data: values,\n        backgroundColor: barColors,\n        borderColor: borderColors,\n        borderWidth: borderWidths,\n        barPercentage: 0.75,\n        categoryPercentage: 0.85,\n      },\n    ],\n  },\n  options: {\n    indexAxis: \"y\",\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    layout: { padding: { right: 90, top: 10 } },\n    plugins: {\n      title: {\n        display: true,\n        text: \"bar-feature-importance · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 22, weight: \"500\" },\n        padding: { bottom: 24 },\n      },\n      legend: { display: false },\n      tooltip: { enabled: false },\n    },\n    scales: {\n      x: {\n        beginAtZero: true,\n        max: maxValue * 1.18,\n        ticks: { color: t.inkSoft, font: { size: 14 } },\n        grid: { color: t.grid },\n        title: {\n          display: true,\n          text: \"Importance (Gini)\",\n          color: t.ink,\n          font: { size: 18 },\n        },\n        border: { color: t.inkSoft },\n      },\n      y: {\n        ticks: { color: t.inkSoft, font: { size: 15 } },\n        grid: { display: false },\n        title: {\n          display: true,\n          text: \"Feature\",\n          color: t.ink,\n          font: { size: 18 },\n        },\n        border: { color: t.inkSoft },\n      },\n    },\n  },\n  plugins: [valueLabelsPlugin],\n});\n"}