{"spec_id":"line-impurity-comparison","library":"chartjs","language":"javascript","code":"// anyplot.ai\n// line-impurity-comparison: Gini Impurity vs Entropy Comparison\n// Library: chartjs 4.4.7 | JavaScript 22.23.2\n// Quality: 89/100 | Created: 2026-08-26\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Splitting-criterion curves across the full probability range [0, 1].\nconst POINTS = 100;\nconst probabilities = Array.from({ length: POINTS }, (_, i) => i / (POINTS - 1));\n\nconst log2 = (x) => Math.log(x) / Math.log(2);\n\nconst giniPoints = probabilities.map((p) => ({ x: p, y: 2 * p * (1 - p) }));\nconst entropyPoints = probabilities.map((p) => {\n  // Edge cases: 0 * log2(0) is undefined, defined as 0 by convention.\n  const term1 = p === 0 ? 0 : -p * log2(p);\n  const term2 = p === 1 ? 0 : -(1 - p) * log2(1 - p);\n  return { x: p, y: term1 + term2 };\n});\n\n// --- Mount -------------------------------------------------------------------\nconst canvas = document.createElement(\"canvas\");\ndocument.getElementById(\"container\").appendChild(canvas);\n\n// --- Custom plugin: annotate the shared maximum at p = 0.5 -------------------\nconst maxImpurityAnnotation = {\n  id: \"maxImpurityAnnotation\",\n  afterDatasetsDraw(chart) {\n    const { ctx, chartArea, scales } = chart;\n    const x = scales.x.getPixelForValue(0.5);\n\n    ctx.save();\n    ctx.strokeStyle = t.inkSoft;\n    ctx.lineWidth = 1.5;\n    ctx.setLineDash([6, 5]);\n    ctx.beginPath();\n    ctx.moveTo(x, chartArea.top);\n    ctx.lineTo(x, chartArea.bottom);\n    ctx.stroke();\n    ctx.setLineDash([]);\n\n    ctx.fillStyle = t.ink;\n    ctx.font = \"16px sans-serif\";\n    ctx.textAlign = \"center\";\n    ctx.fillText(\"Max impurity at p = 0.5\", x, chartArea.top - 10);\n    ctx.restore();\n  },\n};\nChart.register(maxImpurityAnnotation);\n\n// --- Chart ---------------------------------------------------------------------\nnew Chart(canvas, {\n  type: \"line\",\n  data: {\n    datasets: [\n      {\n        label: \"Gini Impurity: 2p(1-p)\",\n        data: giniPoints,\n        borderColor: t.palette[0],\n        backgroundColor: t.palette[0],\n        borderWidth: 4,\n        pointRadius: 0,\n        tension: 0,\n      },\n      {\n        label: \"Entropy: -p·log₂(p) - (1-p)·log₂(1-p)\",\n        data: entropyPoints,\n        borderColor: t.palette[1],\n        backgroundColor: t.palette[1],\n        borderWidth: 3,\n        borderDash: [10, 6],\n        pointRadius: 0,\n        tension: 0,\n      },\n    ],\n  },\n  options: {\n    responsive: true,\n    maintainAspectRatio: false,\n    animation: false,\n    parsing: false,\n    plugins: {\n      title: {\n        display: true,\n        text: \"line-impurity-comparison · javascript · chartjs · anyplot.ai\",\n        color: t.ink,\n        font: { size: 22 },\n        padding: { top: 10, bottom: 34 },\n      },\n      legend: {\n        position: \"bottom\",\n        labels: { color: t.ink, font: { size: 16 }, usePointStyle: true },\n      },\n    },\n    scales: {\n      x: {\n        type: \"linear\",\n        min: 0,\n        max: 1,\n        title: { display: true, text: \"Probability of Positive Class (p)\", color: t.ink, font: { size: 18 } },\n        ticks: { color: t.inkSoft, font: { size: 14 }, stepSize: 0.1 },\n        grid: { display: false },\n      },\n      y: {\n        min: 0,\n        max: 1,\n        title: { display: true, text: \"Impurity Measure\", color: t.ink, font: { size: 18 } },\n        ticks: { color: t.inkSoft, font: { size: 14 } },\n        grid: { color: t.grid },\n      },\n    },\n  },\n});\n"}